Skip to content

media_upload_failed names the real cause, WebP uploads are rejected early, and the failed-sends error tables are corrected

Released: August 4, 2026

media_upload_failed explains what actually went wrong Changed

Section titled “media_upload_failed explains what actually went wrong ”

Sending media by URL failed with this:

{
"status": "failed",
"error": {
"code": "media_upload_failed",
"message": "WhatsApp could not retrieve or process the media URL.",
"provider_code": 131053
}
}

“Could not retrieve” reads as a connectivity problem, so the natural next step was to check whether the URL was reachable. It almost always was. Meta’s own media reference documents 131053 as a mismatched MIME type, and that is what it usually is.

The message now says so:

{
"status": "failed",
"error": {
"code": "media_upload_failed",
"message": "WhatsApp could not fetch or process the media. Check that the URL is publicly reachable and returns a supported Content-Type: images must be image/jpeg or image/png (WebP is accepted for stickers only). CDNs that auto-negotiate format can silently return WebP and trigger this error.",
"provider_code": 131053
}
}

The code and the HTTP status are unchanged. Only the message text moved, so nothing that branches on error.code is affected.

WhatsApp accepts image/jpeg and image/png for image messages. WebP is valid for stickers only.

That matters more than it sounds, because a URL can serve a different format to WhatsApp than it serves to you. Image CDNs built on imgix and similar services perform content negotiation: an auto=format parameter makes them return WebP to any client that advertises support for it. The URL opens correctly in your browser, returns 200, and still fails here.

If you pass third-party image URLs through image.link, pin the format explicitly rather than relying on the CDN default.

Five error codes in the failed-sends guide never existed Fixed

Section titled “Five error codes in the failed-sends guide never existed ”

The Handling failed sends guide documented five error.code values that no Kirimdev endpoint has ever returned. They appeared in the code tables and in the copy-pasteable TypeScript and Python handlers, so anyone who followed the guide wrote switch branches that could never match — and the failure was silent, because an unmatched code simply fell through to the default arm.

Documented (wrong)Actually returned
template_not_approvedtemplate_not_found
template_params_mismatchtemplate_param_mismatch
media_invalidmedia_upload_failed
provider_errorupstream_error
degradedaccount_in_maintenance

degraded was the subtlest of the five: it is a real value, but it is an account status, not an error code. It never appears in error.code.

Two further corrections in the same guide:

  • quota_exceeded was listed as an async send-failure code. It isn’t one — it is a synchronous 402 returned when your Kirimdev plan quota is exhausted, and it never appears as the error.code of a failed message. It has been removed from the async tables and handlers. (When a plan’s monthly message allowance runs out, the failed message carries invalid_request with a quota message, and that allowance resets at the start of the next calendar month.)
  • template_param_format_mismatch was missing entirely. A wrong parameter count and a wrong parameter value format are separate codes with separate fixes, and only the first was documented.

The synchronous HTTP error table was wrong too. Four of its rows named codes and even statuses the API does not use:

Documented (wrong)Actually returned
400 invalid_request400 invalid_field_value
403 phone_number_forbidden404 resource_not_found
409 idempotency_conflict422 idempotency_key_reuse
422 account_not_connected422 whatsapp_number_not_verified

The 403 → 404 correction matters for a subtle reason: an id belonging to another organization returns 404, identical to an id that does not exist, so a caller cannot probe for other tenants’ phone-number ids. A documented 403 would have advertised the opposite.

If you built error handling from this guide, check your branches against the corrected tables. No API behavior changed — only the documentation was wrong.

WebP image uploads are now rejected before they fail at Meta Fixed

Section titled “WebP image uploads are now rejected before they fail at Meta ”

WhatsApp accepts WebP for sticker messages only. An image message with a WebP body is rejected by Meta with the same 131053 above.

Our upload validation nonetheless accepted image/webp for images, in the composer, the media library, and the connector mapping editors. Because nothing in the pipeline transcodes WebP to PNG, the file was sent to Meta unchanged and failed there — a silent 131053 well after the upload appeared to succeed.

WebP is now rejected at upload time for image messages, with an immediate, actionable error instead of a delayed send failure. JPEG and PNG are unaffected. (Broadcast/template image headers already rejected WebP; this brings the chat and media-library paths in line.)

Handling failed sends Error envelope reference