Features Pricing Use cases Compare Blog

WhatsApp Error 2388103: Nine Failures Share One Code

16 min read

The short answer

Error 2388103 is not one failure. Meta's error table lists nine separate rows under that code, each with a different details string, from missing webhooks to an unapproved display name. The code is identical every time, so branch on details, never on the number. Checked 11 September 2026.

WhatsApp numbers screen in the seeded demo workspace listing one connected number with a Default badge and a green Connected badge, its quality rating, messaging tier and template count, beside Refresh, Sync templates, Edit and Disconnect controls.

Why does WhatsApp error 2388103 mean nine different things?

Because Meta's error reference carries nine separate rows under that single code, and the numeral is identical in all nine. What differs is the details string inside error_data, and that string is the only place Meta names the gate you actually failed — webhooks, a display name, a payment method, an approval on either account, or, in one case, the fact that you should not be calling this API at all.

That is not an accident of how somebody typed up a table. Meta's own advice on reading its error responses says the code is half the signal:

"In general, Meta recommends that you build your app's error handling logic around code values and details payload properties." (Meta — WhatsApp error codes)

The shape Meta publishes puts details one level down, nested inside error_data, which is exactly where an integration that logs error.code and nothing else throws the diagnosis away:

{
  "error": {
    "message": "<MESSAGE>",
    "type": "<TYPE>",
    "code": <CODE>,
    "error_data": {
      "messaging_product": "whatsapp",
      "details": "<DETAILS>"
    },
    "error_subcode": <ERROR_SUBCODE>,
    "fbtrace_id": "<FBTRACE_ID>"
  }
}

So a 2388103 recorded as an integer is a dead end: nine remedies collapsed into one number. Recorded with its details string, it is close to self-diagnosing.

The nine detail strings behind WhatsApp error code 2388103 grouped into six causes, with the one meaning you should not be using the migration API marked apart from the rest
One code, nine details, six different things to go and fix.

What are the nine details strings behind code 2388103?

Here they are, as Meta prints them, with the error line and the description Meta pairs it with. Nothing in the response tells you which row you are on except the text itself.

Meta's error line What its description adds Whose side
"Cannot migrate phone number." "Webhooks have not been set up for the destination WhatsApp Business account." Destination
"Your WhatsApp account must be approved" "The destination WhatsApp Business Account must be approved before you can migrate phone numbers." Destination
"Your WhatsApp account's “Messaging For” request must be approved" The destination account's Messaging For request "must be approved by the client." Destination
"The WhatsApp account that this phone number is registered with is not set up correctly." The source account must be approved, and its messaging on behalf of must be approved. Source
"This phone number belongs to a different Business Manager account." "The source and destination WABAs must represent the same business." Both
"Registered name should be present and approved." The number needs an approved display name (name_status is APPROVED) and no pending name change. The number
"Your WhatsApp account does not have a payment account." "Your WhatsApp account must have an active credit line in order to send messages after migration." Billing
"Please add this phone number in your WhatsApp account" "This phone number is eligible to be added directly, and does not need to use phone migration APIs." Wrong API
"There was an error migrating this phone number." "Something went wrong when trying to migrate your phone number." Nobody

(Meta — WhatsApp error codes) Checked against Meta's documentation on 11 September 2026.

Three of the nine are about the destination account, one about the source, one about the pairing of the two, one about the number's display name, one about money, one says you are on the wrong page entirely, and the last names no cause at all. A retry loop written against the code retries all nine identically, and eight of them keep failing.

Does "the same business" mean the same Business Manager?

This is the row that trips the most people, and the most widely repeated reading of it is wrong.

"This phone number belongs to a different Business Manager account. | The source and destination WABAs must represent the same business." (Meta — WhatsApp error codes)

Read as "both accounts must live under one Business Manager portfolio", that sentence would make partner-to-partner migration impossible. It cannot mean that, because the guide the error belongs to is titled "Migrating a business phone number from one Solution Partner to another programmatically" (Meta — Migrate a phone number programmatically). Two different Solution Partners do not share a portfolio, so on that reading the documented feature would refuse its own headline use case.

The reconciliation is in Meta's own remedy for that row, which names the thing that has to match:

"Migrate the phone number into a WhatsApp Business Account that is messaging for the same business as the source WhatsApp Business Account." (Meta — WhatsApp error codes)

Messaging for the same business. The identity that must match is the client's business — the entity both accounts do messaging on behalf of — not the partner's portfolio. A separate 2388103 row uses Meta's own name for that relationship, requiring the destination account's "Messaging For" request to "be approved by the client", and another requires the source account's messaging on behalf of to be approved too. All three describe one chain: the client authorises the source partner, the client authorises the destination partner, and the number moves between two accounts pointing at the same underlying business.

So the fix for this row is almost never moving a portfolio. It is getting the client to approve the destination account's Messaging For request, and confirming the source account's own on-behalf-of approval still stands. Advice to consolidate Business Managers prescribes a large, irreversible action for what is an approval click.

Is there a cooldown before you can migrate a number again?

Not one that Meta documents on this API. The migration guide lists requirements for the phone number, the source account, the destination account and webhooks, and it names no cooldown, no minimum account age, and no cap on attempts anywhere in that list. It does not rule them out either; it is simply silent. The only waiting period the page documents is the 24 hours a migrated template spends at an UNKNOWN quality rating.

Two figures circulate widely and neither appears on Meta's page:

Claim in circulation What Meta's migration guide actually says
A one-to-two-month cooldown after disconnecting a number No waiting period of any length is stated
The destination account must be newer than 48 hours No account age requirement is stated

The second is the more expensive one to believe, because acting on it means deleting and recreating a WhatsApp Business Account — a destructive step, taken to satisfy a rule Meta does not publish. If you find either figure quoted with a Meta link attached, open the link. A claim carrying a citation that does not contain it is worse than one with no citation at all, because it survives a spot check.

Checked against Meta's documentation on 11 September 2026.

What survives a WABA-to-WABA migration and what resets?

Meta's summary sentence is generous, and it is about the phone number:

"Migrated phone numbers keep their display name, quality rating and messaging limit, Official Business Account status, and any High quality message templates previously approved." (Meta — Migrate a phone number programmatically)

Further down the page, in the material on message templates, the same guide contradicts the obvious reading of that, for a different object:

"The quality ratings of templates will NOT be migrated. All migrated templates will start with an UNKNOWN rating." (Meta — Migrate a phone number programmatically)

Both statements are true. The number's quality rating survives; each template's quality rating does not. Summaries that flatten them into "quality is preserved" are wrong in the direction that costs you a campaign.

What moves What happens to it
The phone number Keeps display name, quality rating, messaging limit, Official Business Account status
High quality templates "duplicated and automatically approved" in the destination, if it can fit them
Low quality, rejected, pending templates "will not be duplicated"
Template quality ratings Reset to UNKNOWN for 24 hours, then re-derived if there is data

One word in that table repays attention. Templates are duplicated, not moved — the source account keeps its copies — and only "as long as the destination WABA can accommodate new templates", a template-ceiling condition with an error code of its own (2388019, message template limit exceeded). A destination near its ceiling takes part of your set, and nothing in the migration response announces the shortfall. Count templates on both sides.

WABA-to-WABA or Business app to Cloud API: which migration is this?

Meta publishes two procedures both called migration in casual use, and conflating them is how people end up reading the wrong error table. This article is about the first.

Aspect Account to account Business app to Cloud API
Who it is for Partners holding the client's account A business leaving the handset app
What moves A registered number between two WhatsApp Business Accounts A number out of the WhatsApp Business app onto the API
Templates Duplicated and auto-approved where eligible Nothing to carry; there are none
History Not addressed — the migration guide says nothing about message history "your existing messaging history will be lost"

The second path is explicit about its cost. Meta warns that if you delete the Business app number and then register it for use with Cloud API, "your existing messaging history will be lost, and you will be unable to use that number with the WhatsApp Business app again, unless you deregister the number from Cloud API" (Meta — Migrate an existing WhatsApp number to a business account). The API in this article refuses that case outright — "Business phone numbers in use with the WhatsApp Business App cannot be migrated using this process" — so a number still live in the app never produces a useful 2388103, only a refusal.

If losing the handset is the part you cannot accept, there is a third option: running one number in the Business app and on the Cloud API at once keeps the phone working and adds the API alongside it, with the trade-offs set out in what coexistence stops you doing.

Should you be calling the migration API at all?

For a large share of readers who arrive at a 2388103, the answer is no, and Meta says so inside the error itself:

"Please add this phone number in your WhatsApp account | This phone number is eligible to be added directly, and does not need to use phone migration APIs." (Meta — WhatsApp error codes)

Meta's remedy for that row is one line: "Register and verify the number." No migration call, no source account, no approvals chain.

The guide itself opens with a restriction that most vendor summaries omit:

"Only use this method if you are going to be working with the client using the On-Behalf-Of model (that is, you will create and own the destination WABA and its assets and share them with the client)." (Meta — Migrate a phone number programmatically)

That sentence is the whole filter, and it is worth reading next to what the error table says about the same model. On the row for a source account that is not set up correctly, Meta's stated remedy is not a checklist: the account "may be using the now deprecated On-Behalf-Of ownership model", followed by "Contact support." (Meta — WhatsApp error codes). So the arrangement this API is scoped to is the one Meta's own error page calls deprecated, and a 2388103 on that row is an escalation rather than an approvals hunt.

On-Behalf-Of is also not what Embedded Signup produces, where the customer creates and owns their own WhatsApp Business Account and shares it with a platform. If the customer owns the account, there is no account-to-account move to perform when they change software — the account stays where it is and a different app is granted access to it, which is the handover described in what actually carries over when you switch provider.

That ownership split is also the dividing line between Meta's partner tiers, covered in Solution Partner, Tech Provider and BSP compared. WabaCRM is a Meta-verified Tech Provider, verified 30 July 2026, and connects numbers three ways — Embedded Signup, coexistence, or manual Cloud API credentials — all of which leave the account in the customer's own portfolio with their own payment method attached. None of the three routes a number through the migration API.

A connected WhatsApp number in the demo workspace showing its quality rating, messaging tier and template count beside Refresh and Sync templates controls
Quality rating and messaging tier are read back from Meta after a migration, which is the fastest way to see what actually carried across.

What do 2388091, 2388093 and 2388012 tell you that 2388103 does not?

The neighbouring codes in the 2388 range are narrower than 2388103, and informative precisely because they are specific.

2388091 and 2388093 both carry the same line:

"This phone number isn't eligible to receive/verify a registration code since it is not being migrated. | Phone ownership verification APIs are not available for this use case." (Meta — WhatsApp error codes)

That is a sequencing error, not a configuration one. Meta's procedure runs in four ordered steps — disable two-step verification, initiate phone migration, verify phone ownership, register phone number — and these two codes are what you get for calling the ownership-verification step against a number that never entered a migration at step two. If step two failed with a 2388103 and your code carried on regardless, this is what you see next, and it looks like a second unrelated bug.

Worth knowing before you treat a missing code as a failure: on the verification step the guide says "it may take a few minutes for the code to be delivered" (Meta — Migrate a phone number programmatically).

2388012 is the quiet one:

"This phone number already exists in your list of phone numbers." (Meta — WhatsApp error codes)

Meta describes it as the number you are trying to migrate already being present in your account, with the remedy "Try again with a phone number that is not already present in your WhatsApp account." On a retried job that is frequently good news wearing a red coat: an earlier attempt succeeded and the retry is colliding with its own result. Read the destination's phone number list before treating it as a failure.

Why did every link to Meta's migration guide break?

Because Meta re-homed the WhatsApp documentation set and re-filed this guide underneath its Solution Partners section. The old Cloud API path, ending /cloud-api/phone-numbers/migrate-phone-numbers, returns HTTP 404 as of 11 September 2026. The live page is Migrate a phone number programmatically, filed under business messaging rather than under the Cloud API.

This matters for more than tidiness. Any page still deep-linking the old path is citing a source that no longer resolves, whatever it goes on to say about the API — so check the link before you trust the page. The feature itself was not retired or renamed; only its address moved. The request samples on the live page are pinned at v25.0, released 18 February 2026 and one version behind the current v26.0 of 29 July 2026 (Meta — Graph API changelog).

The request shape documented there is a POST against the destination account, at Meta's own sample version rather than the newest one:

POST https://graph.facebook.com/v25.0/<DESTINATION_WABA_ID>/phone_numbers
  cc=<COUNTRY_CODE>
  phone_number=<PHONE_NUMBER>
  migrate_phone_number=true

One more line on that page is worth reading before anyone plans a bulk cutover: "The API does not support bulk migration; business phone numbers must be migrated individually." (Meta — Migrate a phone number programmatically)

In what order should you clear a 2388103?

The code tells you nothing and the details string tells you everything, so the order is: read the string, then work outwards from the cheapest fix.

  1. Log the details value, not the code. If your integration already discarded it, reproduce the call by hand and capture the whole error_data object. Every step below depends on knowing which of the nine rows you are on.
  2. Check whether you belong here. If details mentions being eligible to be added directly, stop. Register and verify the number on the destination account and close the ticket.
  3. Clear the destination account's setup. Three of the nine rows live here: at least one app subscribed to webhooks for the destination account, the account itself approved, and the client's Messaging For request approved.
  4. Clear the source side and the pairing. Confirm the source account is approved, that its messaging on behalf of is approved, and that both accounts are messaging for the same client business rather than sitting in the same portfolio. If the source account is on the On-Behalf-Of ownership model, stop retrying: Meta's remedy for that row is to contact support, because it calls that model deprecated.
  5. Check the number. An approved display name, name_status reading APPROVED, and no pending name change request in the queue.
  6. Check billing on the destination. An active credit line, because Meta gates the migration on the account's ability to send after it.
  7. Only then treat it as Meta's problem. One row says nothing beyond that something went wrong. That row, with the fbtrace_id from the same response, is a support ticket rather than a configuration hunt.

The two steps that resolve most cases — reading the string, and confirming you should be using this API at all — cost about five minutes between them. The other direction means auditing portfolio membership for a problem that was a missing webhook subscription.

Every Meta quotation on this page was read from Meta's own documentation on 11 September 2026. Meta changes that documentation without notice; the linked pages are authoritative and this one is not.

Questions people also ask

Can I migrate a WhatsApp number without losing my approved templates?

Partly. Meta's migration guide says all High quality message templates in the source WhatsApp Business Account will be duplicated and automatically approved in the destination account, as long as the destination can accommodate new templates. That conditional is worth reading twice, because a destination already near its template ceiling takes fewer than you sent and nothing announces the shortfall. Low quality, rejected, or pending templates are not duplicated at all. Duplication is also not the same as moving: the source keeps its copies, and the quality rating attached to each template does not travel. Plan for a partial set rather than a clone.

Does a migrated number keep its quality rating?

The number does. Its templates do not, and the two facts sit in different sections of the same Meta page. The summary says migrated phone numbers keep their display name, quality rating and messaging limit, Official Business Account status, and any High quality message templates previously approved. Further down, the same guide states that the quality ratings of templates will not be migrated, that all migrated templates start with an UNKNOWN rating, and that the UNKNOWN rating remains for the first 24 hours before a new one is generated if there is sufficient data. Careless summaries collapse both into quality is preserved.

Who is charged for messages sent around the time of a migration?

Meta splits the bill at the migration itself. Its guide states that messages sent before migration are charged to the source business, and messages sent after migration are charged to the destination business. That boundary is cleaner than it sounds, because no invoice is reassigned retroactively and neither side inherits the other's unbilled volume. It also means the destination account needs working billing before the first send after the move, which is precisely what one of the nine 2388103 rows refuses on: your WhatsApp account must have an active credit line in order to send messages after migration.

Can a WhatsApp test number be migrated to a live account?

No. Meta's migration guide states that test business phone numbers issued by WhatsApp cannot be migrated. The same list rules out a second common case: business phone numbers in use with the WhatsApp Business App cannot be migrated using this process. Neither refusal is a configuration you can argue with from the API side, so both are worth checking before anyone spends an afternoon on request payloads. A test number is scaffolding Meta issues for development, and a number still running inside the Business app belongs to the separate app-to-Cloud-API path, which is a different procedure with different consequences.

Does Meta publish a waiting period between number migrations?

Not on the page that governs this API. Meta's programmatic migration guide lists requirements for the phone number, the source account, the destination account and webhooks, and names no cooldown, no minimum account age and no cap on attempts anywhere in that list. The guide is silent on all three rather than ruling them out. The only waiting period it documents is the 24 hours a migrated template spends at an UNKNOWN quality rating. Vendor pages quoting a one-to-two-month cooldown, or a rule that an account must be newer than 48 hours, are not quoting Meta.

Keep reading

Your customers are already on WhatsApp

Free for your first 1,000 contacts, with no time limit and no card. Setting up the workspace takes minutes; connecting a number takes as long as Meta's own review of it.

Sign up with your company email address. No sales call, no onboarding fee, nothing to schedule.

Why this is safe to point your customer list at

Payments are processed by Razorpay on their own checkout — your card details are never entered on, or stored by, WabaCRM. Every inbound WhatsApp webhook is checked against its signature before it is trusted.

Tech Provider is a Meta platform access tier — not a partnership, a reseller agreement or an endorsement.