Errors
The source meta or whabuzz contract, the WhaBuzz error codes, and how to read Meta's errors.
Every error response says who produced it, in the body and in a header. Check source first.
source | Meaning | HTTP status |
|---|---|---|
whabuzz | WhaBuzz stopped the request: auth, validation, account state, WhaBuzz's own limits. Meta was not called, or could not be reached. | WhaBuzz's |
meta | Meta answered with an error. WhaBuzz returns it verbatim. | Meta's own status |
The header X-WhaBuzz-Error-Source: whabuzz or meta repeats it, so you can branch without parsing JSON.
#WhaBuzz errors
{
"source": "whabuzz",
"error": {
"code": "number_not_connected",
"message": "Number 1013622581841046 is not connected.",
"details": { "connection_detail": "no_verified_endpoint" }
},
"request_id": "req_01JAB3W1Z4B7D0F3H6K9N2Q5S8"
}jsonAlways log request_id (also the X-WhaBuzz-Request-Id header). It is what support looks up.
| HTTP | code | When | details |
|---|---|---|---|
| 400 | invalid_request | Malformed JSON, missing or invalid field, missing X-WhaBuzz-Tenant | field errors |
| 401 | unauthorized | Missing, wrong, revoked or expired API key | |
| 403 | forbidden | The key's role cannot do this | |
| 403 | tenant_not_approved | Account is pending_approval or rejected | |
| 403 | tenant_suspended | Account is suspended | reason |
| 403 | email_not_verified | Console sign-in before the email link was used | |
| 404 | not_found | No such resource, or not yours | reason: "payload_expired" when a replay is outside retention |
| 409 | number_not_connected | Send from a number that is not connected | connection_detail |
| 409 | idempotency_conflict | Same Idempotency-Key still in flight | |
| 422 | idempotency_conflict | Same Idempotency-Key with a different body | |
| 422 | webhook_verify_failed | Your endpoint failed the verify ping | http_status, body_excerpt |
| 429 | rate_limited | Sign-up, login or password reset only. Retry-After is set. | |
| 502 | meta_unreachable | Graph API did not answer within 15 seconds. The outcome is unknown. | |
| 400 | invalid_token | Sign-up or password-reset link is unknown, used or expired | |
| 409 | conflict | The resource is in the wrong state for this action, or the WABA is already connected to another account | |
| 409 | limit_reached | A per-account cap, for example the number of webhook endpoints | |
| 503 | billing_disabled | Any /v1/billing route before billing is switched on | billing_enabled: false |
| 503 | billing_not_configured | Billing is on but the payment gateway is not configured | |
| 502 | billing_gateway_error | The payment gateway answered with an error | |
| 502 | meta_token_invalid | The Embedded Signup token failed Meta's validation | |
| 500 | meta_not_configured | WhaBuzz's Meta credentials are missing (our fault, not yours) | |
| 500 | internal_error | A fault in WhaBuzz. Retry; report the request_id if it persists. The message is always Internal error. |
meta_unreachable is the one to handle carefully: the message may or may not have been sent. Retry with the same Idempotency-Key (see Idempotency) rather than composing a new send.
#Reading Meta errors
When Meta refuses a call, you get Meta's HTTP status and Meta's error object under error, unchanged:
{
"source": "meta",
"error": {
"message": "(#131030) Recipient phone number not in allowed list",
"type": "OAuthException",
"code": 131030,
"error_data": {
"messaging_product": "whatsapp",
"details": "Recipient phone number not in allowed list: Add recipient phone number to recipient list and try again."
},
"error_subcode": 2655007,
"fbtrace_id": "AqN2fZtPLm1oV0xK3wRhjQe"
}
}jsonReading it:
error.codeis the number to branch on. WhaBuzz never rewrites it.error.error_data.detailsis Meta's plain-language explanation. Show it in your logs.error.fbtrace_idis what Meta support asks for. Keep it.- The HTTP status is Meta's: 4xx means your request or account state, 5xx means Meta's side. Do not auto-retry 4xx.
The example above, 131030, is what you get while a WABA is in test mode and the recipient is not on its allowed list. Add the number to the list in Meta's manager, or finish business verification.
Common ones: 131047 (re-engagement: the 24-hour window is closed, use a template), 131026 (message undeliverable), 132000 series (template parameter problems), 130429 (throughput), 131056 (pair rate limit), 190 (token expired or invalid; reconnect the number).
If Meta's response is not JSON, WhaBuzz wraps it as {"source":"meta","error":{"raw_body":"<first 4 KB>"}}.
The complete list, with Meta's recommended fix for each, is in Meta's documentation: Cloud API error codes.
#Errors inside events
Failures after acceptance arrive as events, not HTTP errors: a message.status with status: "failed" carries status.errors[] in Meta's format. The same error.code numbers apply.
This page as Markdown: /errors.md. All docs in one file: /llms-full.txt.