# WhatsApp connection troubleshooting
Settings → WhatsApp connection talks to the Meta Graph API in a fixed
order when you click **Save Configuration**. When one of those calls
fails, wacrm now tells you *which* call failed, *which field* to check,
and gives you the Meta error code and trace id to quote to Meta support
(issue #505). This page lists the common causes and the exact text
wacrm shows for each.
## What Save Configuration does
| Step (shown in the error details) | Meta call | Proves |
| --- | --- | --- |
| *(before any Meta call)* | — | Phone Number ID and WABA ID are digit strings |
| `verify_number` | `GET /{phone_number_id}` | the token can read the number |
| `waba_phone_numbers` | `GET /{waba_id}/phone_numbers` | the number really lives under that WABA |
| `register` | `POST /{phone_number_id}/register` (only when a PIN is entered) | the number is registered with the Cloud API for inbound webhooks |
| `subscribe_waba` | `POST /{waba_id}/subscribed_apps` | the WABA is subscribed to your Meta App, so webhooks are delivered |
The first four failures stop the save; nothing is written until the
cause is fixed. A `register` failure still saves the credentials (so
you can retry with only the PIN) and shows the reason in the
*Registration status* banner.
**Test API Connection** re-runs `verify_number` with the stored token
and, when a WABA ID is on file, reads `GET /{waba_id}/subscribed_apps`
and reports whether the WABA is subscribed to an app. Valid
credentials plus an unsubscribed WABA is exactly the "connected but no
messages arrive" state.
## Reading the error details
Under the actionable message, small muted text shows:
```
Step: verify_number · Meta error code: 190/463 · Trace ID: AbCdEf...
Meta said: Error validating access token: Session has expired ...
```
* **Step** — the row in the table above.
* **Meta error code** — `code/subcode` from Meta's envelope. The
[Cloud API error code reference](https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes)
documents every value.
* **Trace ID** — Meta's `fbtrace_id`. Meta support can look up the
request with it; quote it together with the code.
The HTTP status also tells you who has to act: **400** means the fix
is on the settings form (token, ids, PIN); **502** means Meta has to
change something (rate limit, restriction, outage).
## Common causes and what wacrm shows
### Phone Number ID is not an id
*Cause:* the phone number (`+1 555 ...`) or a display name was pasted
instead of the numeric id.
> Phone Number ID must contain only digits — it is the numeric id shown
> under Meta → WhatsApp → API Setup, not the phone number itself.
The same check runs for the WABA ID:
> WhatsApp Business Account ID must contain only digits — copy it from
> Meta → WhatsApp → API Setup.
### Access token expired or invalid (code 190)
*Cause:* the 24-hour temporary token from the API Setup page was used,
or a System User token was revoked / reset.
> The access token has expired. Temporary tokens from the API Setup
> page expire after 24 hours. Generate a permanent token in Meta
> Business Settings → System Users → Generate token, with the
> whatsapp_business_management and whatsapp_business_messaging
> permissions, and paste it into Permanent Access Token.
(The first sentence varies with the subcode: "has been invalidated" for
460/467, "Meta rejected the access token as invalid" otherwise.)
### Token lacks permissions (code 10, 200–299)
*Cause:* the System User token was generated without
`whatsapp_business_management` / `whatsapp_business_messaging`, or the
System User was never assigned to the WABA.
> The access token is not allowed to perform this action (subscribing
> the WhatsApp Business Account to the app). Its System User needs the
> whatsapp_business_management and whatsapp_business_messaging
> permissions AND must be assigned to this WhatsApp Business Account
> (Business Settings → System Users → Add assets → WhatsApp accounts).
> Then generate a new token.
Code 131005 (access denied) gets a similar message naming the id that
was refused.
### Wrong Phone Number ID or WABA ID (code 100 "Unsupported get request", code 33)
*Cause:* the id is mistyped, or it belongs to a different Business
portfolio than the one the token was generated in.
> Meta cannot find Phone Number ID 1234567890, or the business that
> owns the access token does not own it. Copy the Phone Number ID
> exactly from Meta → WhatsApp → API Setup and check the token was
> generated inside the same Business portfolio.
When the failing step is WABA-scoped the message names the
*WhatsApp Business Account ID* instead.
### Phone number is under a different WABA
*Cause:* both ids are valid, but the WABA you typed does not own the
number. Before #505 this saved fine and subscribed the wrong WABA — the
webhook simply never fired.
> Phone Number ID 111 does not belong to WhatsApp Business Account 999.
> Meta lists these numbers under it: +1 555-0100 (222), +1 555-0200
> (333). Check both values in Meta → WhatsApp → API Setup: the WABA ID
> shown there must be the one that lists this phone number.
### Number not registered with the Cloud API (code 133010)
> This phone number is not registered with the WhatsApp Cloud API yet.
> Enter the two-step verification PIN below and save again so wacrm can
> register it (POST /register).
### Wrong two-step PIN (codes 133005, 136025)
> The two-step verification PIN is wrong. Use the 6-digit PIN set in
> WhatsApp Manager → Phone numbers → Two-step verification (or reset it
> there), then save again.
Too many wrong guesses (133008 / 133009) lock attempts for a while:
> Meta has temporarily locked PIN attempts for this number after too
> many wrong guesses. Wait a while before saving again with the correct
> PIN.
### Account restricted by Meta (code 131031, 368)
Nothing in wacrm fixes this — it is a Meta policy or verification
state.
> Meta has restricted or locked this WhatsApp Business Account, so
> nothing in wacrm can connect it. Open Meta Business Manager → Account
> quality (or WhatsApp Manager → Overview) to see the restriction and
> appeal it.
### Rate limited (codes 4, 17, 32, 613, 80007, 130429, …)
> Meta is rate-limiting this app or WhatsApp Business Account right
> now. Nothing needs changing — wait a few minutes and try again.
### Temporary Meta-side failure (codes 1, 2, 131000, 133004, 133016)
> Meta returned a temporary error while reading the phone number (code
> 131000). Retry in a minute; if it keeps happening, check
> metastatus.com and quote the trace id to Meta support.
### Anything else
Unknown codes keep Meta's own words plus the trace id:
> Meta returned an error while registering the phone number (code
> 12345/6): . Trace id AbCdEf.
If the server cannot reach `graph.facebook.com` at all:
> Could not reach the Meta Graph API while reading the phone number:
> fetch failed. Check that this server has outbound internet access to
> graph.facebook.com and try again.
## Credentials valid, but no messages arrive
1. Click **Test API Connection**. If it says *"The WhatsApp Business
Account is not subscribed to this app"*, re-enter the token and save
again — the save subscribes the WABA.
2. Check the *Registration status* banner. *Not registered* means
`/register` never succeeded for this number; enter the two-step PIN
and save.
3. Click **Verify with Meta** for a per-check breakdown
(`phone_metadata_ok`, `waba_subscribed_to_app`,
`locally_marked_registered`).
4. Confirm the webhook itself: in the Meta App → WhatsApp →
Configuration, the callback URL must be `https:///api/whatsapp/webhook`,
the verify token must match the one saved here, and the `messages`
field must be subscribed. `META_APP_SECRET` in the server
environment must be *that* app's secret, or every delivery is
rejected with a 401 before wacrm looks at it.
## Where the mapping lives
* `src/lib/whatsapp/meta-error-explain.ts` — code → explanation, field,
and 400/502 side. Pure and unit-tested; add new codes there.
* `src/lib/whatsapp/waba-pairing.ts` — id format check and the
phone-under-WABA check.
* `src/app/api/whatsapp/config/route.ts` — the connect flow. Every
Meta failure returns `{ error, meta: { code, subcode, fbtrace_id,
step, field, message } }`.