Skip to main content

Sends blocked by the reassigned-number gate

A send refuses with HTTP 422 and code MESSAGING_RND_REASSIGNED. The reassigned-number (RND) scrub your organization enabled found that the destination number was permanently disconnected after the date your consent ledger records, so the number may now belong to a new subscriber and the send is refused before dispatch. This page walks what the refusal means, how to confirm the reassignment, and the paths that clear it.
RND scrubbing is a tenant-owned control. Your organization opted in under Settings → Compliance; Orbit enforces the posture you set and records every block in your audit log. The posture decision, including disabling the scrub, is always yours.

1. What you see

The send call returns:
details.to is the destination redacted to its first digits; the full identifier stays in your own records, not in the response. The refusal surfaces in three places:
  • The send response — the 422 above, for synchronous API sends.
  • Campaign and flow sends — the individual send is recorded as failed with this code in the campaign’s failure view; the rest of the campaign continues.
  • Message webhooks — if you subscribe to message lifecycle events, the failure event for that send carries the same code.
Every block also writes an audit row (Settings → Audit log) naming the channel and the refusal reason, so a compliance review can see what was refused and why. The gate applies to US (+1) SMS and MMS destinations on organizations that enabled the scrub. One-time-code sends to phone channels use a sibling guard, VERIFY_RND_REASSIGNED, covered on its own page.

2. Why the gate exists

When a number is permanently disconnected, the carrier eventually recycles it to a new subscriber. A message sent to a recycled number reaches a stranger who never consented to your traffic: a wrong-recipient exposure with no TCPA safe harbor. The FCC maintains the Reassigned Numbers Database (RND) so senders can check a number against permanent-disconnect records before contacting it (the 47 CFR § 64.1200(m) safe harbor), and your enabled scrub does exactly that on the send path: when a permanent disconnect on record post-dates the consent date in your ledger, no safe harbor applies and the send is refused. This refusal can only fire because your organization opted in. RND scrubbing defaults off; enabling it, and the strictness it applies to your sends, is a posture decision your compliance team owns. Orbit provides the control and enforces it faithfully; it does not mandate the posture.

3. Confirm the reassignment

Run the lookup on the destination with the consent date you have on record:
The response data carries the verdict: The comparison is the whole decision:
  • Disconnect after your consent date → the consent you hold predates the reassignment risk; take a fix path from Section 4.
  • Disconnect before a newer consent date you hold → your ledger is stale. The gate evaluated the latest grant it could find; record the newer grant (fix path B) so the evaluation uses it.
  • No disconnect on record → the 422 you received is not this gate’s current view of the number; re-check the error.code on the refusal against Compliance send-gate error codes.
Two adjacent responses are worth knowing:
  • 403 RND_SCRUB_NOT_ENABLED on the lookup means the scrub flag is off for your organization. While it is off, sends are not scrubbed and this page’s 422 cannot originate from the RND gate.
  • 409 when enabling the flag means no RND snapshot is configured for the deployment yet; until a feed is synced every verdict is no_data. See RND scrubbing.

4. Fix paths

A. Remove or re-verify the contact. If the number is genuinely lost to you, suppress or remove the contact before the next campaign run; a recycled number is a suppression candidate, not a retry candidate. If the person still owns the number, re-verify ownership with them directly (a confirmation send on an unaffected channel, a double-opt-in handshake, or an out-of-band check) and keep the evidence. B. Refresh the consent evidence. Record the freshly confirmed grant in your consent ledger (Consent API or the managed double-opt-in flow). The gate evaluates the latest live grant for the contact and channel; once the recorded consent date post-dates last_disconnect_date, the lookup returns status: "no" and sends resume without any settings change. C. Adjust your RND posture. The scrub is a tenant toggle: Settings → Compliance, the FCC Reassigned Numbers (RND) scrubbing section, or PUT /api/v1/compliance/rnd/settings for owner/admin. Narrowing or disabling the scrub stops the refusals immediately (within the settings cache window, about a minute) — and moves the reassigned-number risk back onto your organization, which is exactly the trade the toggle exists to let you make. Every change to the flag writes an audit row, so the posture decision and its timestamp are provable in a review. On fail-open versus fail-closed: against a confirmed post-consent disconnect the gate fails closed — the send is refused. Against an unevaluable check (a feed or lookup error mid-send) the gate fails open and the send proceeds, because the scrub is an additive protection your organization layered on; an outage in it must not black-hole your traffic. Disabling the toggle is not the fail-open path — it removes the protection entirely, deliberately and on the audit record.

5. What never works: blind retries

Resending the same payload returns the same 422. The inputs to the decision are your consent ledger and the RND record; neither changes between attempts, so there is nothing for a retry to wait out. This is not a rate limit, not a carrier congestion error, and it carries no retry-after window. Blind retries burn send budget, accumulate blocked rows in campaign views, and add audit noise without moving the verdict. Change the data (fix paths A or B) or the posture (fix path C) first; then send once and confirm the lookup verdict flipped before resuming the campaign.

6. Escalation bundle

If the lookup returns status: "yes" against a consent date you can prove post-dates the disconnect, or a refusal persists past the settings cache window after a posture change, open a support ticket carrying:
  • The HTTP status and error.code from the refusal.
  • meta.request_id from the refusal envelope.
  • The destination as recorded on your side plus its redacted form (details.to, the MSISDN hash as it appears in your audit row) so the row can be correlated without resending full numbers.
  • The consent date the lookup was given and the last_disconnect_date it returned.
That packet lets support replay the verdict without asking you for anything else.

Cross-references