fix(whatsapp): treat empty phone fields as absent by Pitchfork-and-Torch · Pull Request #992 · vercel/chat · GitHub
Skip to content

fix(whatsapp): treat empty phone fields as absent - #992

Merged
bensabic merged 1 commit into
vercel:mainfrom
Pitchfork-and-Torch:fix/whatsapp-empty-phone-fields
Oct 7, 2026
Merged

bensabic merged 1 commit into
vercel:mainfrom
Pitchfork-and-Torch:fix/whatsapp-empty-phone-fields

Conversation

@Pitchfork-and-Torch

Copy link
Copy Markdown
Contributor

Summary

Fixes #925.

Meta can send from and wa_id as empty strings, instead of omitting them, for a username user who doesn't share their phone number. An earlier revision of Meta's business-scoped user IDs page described both fields as "New value (empty)", and Azure Communication Services warns that from "may be empty or null". The current Meta page says the fields are omitted. The adapter should handle both shapes.

fields() resolved the user with ??, which keeps "":

const phone = inbound.system?.wa_id ?? inbound.from ?? contact?.wa_id; // ""
const userId = phone ?? bsuid ?? parent;                                // ""
return userId ? { ... } : null;                                         // null

So resolve() returned null, and handleWebhook dropped the message with WhatsApp message has no user identifier, even though from_user_id was present. In resolve(), a system message with from: "" also set the canonical fallback to "", so the new BSUID was aliased to an empty user ID.

This PR uses || in fields() and for the system-message source in resolve(), so an empty identifier falls through to the BSUID. Payloads that omit the fields, or that carry a real phone number, resolve the same way as before.

Test plan

Two regression tests in packages/adapter-whatsapp/src/index.test.ts:

  • Empty phone fields for a username user: a webhook with from: "", wa_id: "", and from_user_id reaches processMessage on whatsapp:123456789:<BSUID>. The reply is sent with recipient: <BSUID> and no to.
  • System message with an empty sender: after a system message with from: "" and system.user_id: "US.NEW", the alias for US.NEW points to US.NEW, not "".

Both tests fail on main:

× treats empty phone fields as absent for username users
  AssertionError: expected "vi.fn()" to be called once, but got 0 times
× treats an empty system message sender as absent
  AssertionError: expected null to be 'US.NEW'

With only the fields() change, the second test still fails with expected '' to be 'US.NEW'. That failure is why resolve() needs the change too.

With the full fix:

  • pnpm --filter @chat-adapter/whatsapp test: 5 files, 232 tests pass
  • tsc --noEmit in the adapter: passes
  • biome check on the changed files: no issues

Checklist

  • All commits are signed and verified
  • All commits are signed off for the DCO (git commit -s)
  • pnpm validate passes (I ran the adapter's test suite, typecheck, and Biome check, not the full monorepo validate)
  • Changeset added
  • Documentation updated (sample-messages.md now says the phone fields can be empty strings)

Meta can send `from` and `wa_id` as empty strings, instead of omitting
them, for a username user who does not share their phone number. The
identity lookup used `??`, which keeps the empty string, so `fields()`
returned no user ID and the webhook dropped the message with "WhatsApp
message has no user identifier". A system message with an empty `from`
also aliased the new BSUID to an empty user ID.

Use `||` so an empty identifier falls through to the BSUID.

Fixes vercel#925

Signed-off-by: Jon Bailey <297513015+Pitchfork-and-Torch@users.noreply.github.com>
@Pitchfork-and-Torch
Pitchfork-and-Torch requested a review from a team October 5, 2026 18:19
@vercel

vercel Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@bensabic
bensabic merged commit 3aca83c into vercel:main Oct 7, 2026
13 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WhatsApp: messages from username users are dropped: Meta sends from/wa_id as empty strings, not omitted

2 participants