WhatsApp not sending
Fix failed WhatsApp sends — map the failure code (templates, opt-outs, connection, phone, variables, media) and get messages flowing again.
WhatsApp not sending
WhatsApp messages are failing, or they "send" but the customer never gets them. The CRM refuses sends for a small, well-defined set of reasons and records the exact one on the message. Find the failure code, fix its cause, resend. Almost nothing here is guesswork — the system tells you what is wrong.
Who this is for: workspace admins managing the WhatsApp channel, and super admins who own the platform WhatsApp configuration.
Problem
Messages stuck or failed in an automation, an inbox reply that never delivers, or templates that cannot be sent at all.
What you see
| Symptom | Where |
|---|---|
A failed message with a failure_code |
Lead message record / conversation view |
| Connection not connected / needs reconnect | Admin → Settings → WhatsApp (/admin/settings/whatsapp), and the System Health WhatsApp card |
Templates stuck pending or marked rejected |
Admin → WhatsApp templates (/admin/whats-app-templates) |
| The composer hint about the 24-hour window | Admin → Conversations (/admin/conversations) |
queue_failures above zero |
System Health WhatsApp card (counts failed SendLeadMessage jobs) |
The failure codes, decoded
| Failure code | Meaning | Fix |
|---|---|---|
WHATSAPP_NOT_CONNECTED |
The workspace has no working WhatsApp connection | Reconnect under Admin → Settings → WhatsApp |
TEMPLATE_UNAVAILABLE |
The named template does not exist on the connection | Sync templates, then pick a template the CRM actually has |
TEMPLATE_NOT_APPROVED |
Template exists but Meta has not approved it | Wait for approval or choose an approved template; chase rejects in Meta |
OPTED_OUT |
The contact sent a stop keyword (exact match) | Respect it — see the opt-out section below |
NO_VALID_PHONE |
The contact's number is missing or not sendable | Fix the phone number on the contact (10-digit Indian format) |
MISSING_TEMPLATE_VARIABLE |
The template needs variables the message did not supply | Fill the template variables in the automation/message |
MEDIA_NOT_FOUND |
Template has a media header, but the referenced file is gone | Re-upload the media (or send without the media header) |
The checks run in that order — the first failing gate is the code you get, so fixing one code may reveal the next. Work through them until the message sends.
Likely causes
- WhatsApp connection revoked/expired (Meta side), or credentials edited wrongly.
- Templates: not synced, not approved, or renamed in Meta.
- Contact opted out with a stop keyword, or a phone number that cannot receive WhatsApp.
- Sending free-form messages outside WhatsApp's 24-hour reply window — the composer warns you; only approved templates are acceptable outside the window.
- A stalled queue: the message is fine, the worker is not running (see Incident response).
Quick fix
- Open the failed message and read its
failure_code— use the table above. - Admin → Settings → WhatsApp → Test Message. If the test fails, fix the connection first; if it succeeds, the connection is fine and the failure is message-specific (template, opt-out, phone, media).
- If several messages failed at once, check the System Health WhatsApp card's
queue_failuresand the worker state.
Step-by-step fix
- Connection — connect WhatsApp Business. Then run Test Message from the settings page. Connection fields you may need to verify: WABA ID, Phone Number ID, display number, access token, app secret, verify token. Actions available: Sync Templates, Test Message, Reconnect, Disconnect.
- Templates — open Admin → WhatsApp templates, sync, and confirm the template you send with is
approved. Only approved templates may be used to start/continue conversations outside the 24-hour customer-service window. - 24-hour window — inside the window (customer messaged you recently) free-form text is fine; outside it, use a template. The composer tells you when you are outside the window.
- Opt-outs — when a customer replies with a stop keyword (exact match — defaults are
stop,unsubscribe,do not message; the workspace can change the list), the contact is marked opted out (whatsapp_opted_out_at, sourceinbound_keyword, with the reason recorded andwhatsapp_opted_outactivity on the contact). Sends to that contact then fail withOPTED_OUT— this is the system protecting you from complaints. Only remove the opt-out if the customer explicitly asks to resume, and do it deliberately on the contact record. - Queue — if nothing is sending at all (not even tests), it is a queue/worker problem, not WhatsApp: read the queue runbook in Incident response and check
queue_failureson System Health. - Webhook health — the inbound webhook URL Meta calls is
{app URL}/api/messaging/whatsapp/webhook/{tenant}/{token}; if deliveries/read receipts are not updating, verify this URL and token against Meta's configuration. - Retry the message — after fixing the cause, resend. An automation that failed once will not silently retry by itself.
Admin fix
- Reconnect the channel, sync templates, and fix the contact (number, opt-out state) — everything above is admin-panel work.
- If templates are stuck
pendingfor days, the delay is Meta's review, not the CRM — templates must be approved on Meta's side; rejected ones must be edited and resubmitted there.
Developer fix
- The guard chain in
SendWhatsAppActionruns in this exact order:TEMPLATE_UNAVAILABLE→TEMPLATE_NOT_APPROVED→OPTED_OUT→WHATSAPP_NOT_CONNECTED→NO_VALID_PHONE→MISSING_TEMPLATE_VARIABLE→MEDIA_NOT_FOUND. Failures persist as failedLeadMessagerows with thefailure_codeabove. - Opt-out handling lives in
WhatsAppMessageService: exact keyword match against defaults['stop', 'unsubscribe', 'do not message'], overridable per workspace (automation.whatsapp_optout_keywords); it stampswhatsapp_opted_out_at,whatsapp_opt_out_source=inbound_keyword, and the reason. - The System Health WhatsApp card counts
failed_jobswhose payload referencesSendLeadMessage— a fast systemic read. - The 24-hour window is enforced by WhatsApp itself; the CRM surfaces it as a composer hint, not a hard block — sends outside the window with non-template content will be rejected by Meta.
Logs to check
- The failed message's
failure_codeand any provider response — always the fastest source. storage/logs/laravel.log— WhatsApp API errors and queue failures around the send time.- System Health WhatsApp card — connections, templates, and messages today / delivered / read / failed counts.
When to escalate
- The connection reconnects and tests pass, but all template sends fail for every contact.
- Meta restrictions on the number/business (quality rating, account review) — that is a Meta-side action only the business owner can resolve.
- Deliveries show sent but no
delivered/readfor a whole day with everything green in the CRM — check the number status in Meta Business Manager, then escalate to the super admin.
Related guides
Was this page helpful?
Thanks — noted. ✦