> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting: voice destination and emergency blocks

> Resolve 422 EMERGENCY_CALLING_NOT_SUPPORTED, 422 VOICE_DNO_BLOCKED, 429 VOICE_COUNTRY_RATE_LIMITED, and VOICE_CALLER_ID_REJECTED pre-flight rejects — map each code to the gate that fired and the fix you own.

# Troubleshooting: voice destination and emergency blocks

A pre-flight destination block rejects an outbound voice call before any
SIP leaves the platform — no trunk, codec, or carrier change will clear
it, and a blind retry just replays the same check. The block comes in
one of four codes, and each one belongs to a specific gate.

This page maps every code to its gate and the fix you own. For the
per-destination auto-blocks that fire *after* the pre-flight checks (the
traffic-pumping / Wangiri sweep), see
[Voice destination auto-blocks](/compliance/voice-destination-auto-blocks) —
source until the fix loop below has nothing left to blame.

## Decision matrix — which gate fired

Find the error code first, then jump to its section below. Each gate
takes one of three controls you own — the country allow-list, the
caller-id list, or the rate window — so triage ends in a small set of
places.

| Error code                              | Gate that fired                                                                                      | Control you own                                                        | Go to                                                  |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------ |
| `EMERGENCY_CALLING_NOT_SUPPORTED` (422) | The destination resolved to an emergency short code (911 / 112 / 999 / 000)                          | None to change — **reroute the traffic**                               | [Emergency short codes](#emergency-codes)              |
| `VOICE_DNO_BLOCKED` (422)               | The caller ID you presented matches a Do-Not-Originate prefix                                        | **Caller-id list** — present a DID you own                             | [Do-Not-Originate caller-id](#voice-dno-blocked)       |
| `VOICE_COUNTRY_RATE_LIMITED` (429)      | The per-destination-country sliding-window cap tripped                                               | **Rate window** — spread or scope the burst                            | [Per-country rate window](#voice-country-rate-limited) |
| `VOICE_CALLER_ID_REJECTED` (403)        | An INVITE on a customer trunk presented a caller-id outside the trunk allow-list or the org DID list | **Caller-id list on the trunk** — add the caller-id or use a valid DID | [Trunk caller-id](#voice-caller-id-rejected)           |

## Emergency short codes<a id="emergency-codes" />

`422 EMERGENCY_CALLING_NOT_SUPPORTED` fires when the number you dial
resolves to an emergency short code. The check lives on the outbound
dial path itself — a campaign, an ad-hoc dial, and a SIP-trunk
origination all take the same block.

The reject is charged against a platform-wide deny-list — US **911**, EU
**112**, UK **999**, AU **000**. Adding any one of those as a destination,
in any locale or array shape, returns a 422 every time.

**Fix this by routing to a valid PSTN number**, not by working around it:

* Route the call through a real number on your configured trunk — the
  exception is not a caller you can re-server.
* The platform will still issue an integration-friendly
  `docs_url` pointer to the
  [emergency-calling page](/voice/emergency-calling) on every block, so a
  branch on the error code can surface the disclaimer verbatim.

A 422 in this class is not recoverable with configuration — the
destination itself is the problem, and the gate takes the exact same
shape for every block size and source.

## Do-Not-Originate caller-id blocked<a id="voice-dno-blocked" />

`422 VOICE_DNO_BLOCKED` fires when the resolved **caller-id** (the `from`
number you present) matches a Do-Not-Originate (DNO) entry. A DNO list
holds the numbers that must never appear as a calling-party number —
invalid, unallocated, or inbound-only lines (spoofed government or bank
lines, inbound-only toll-free, unassigned ranges). Matching is
prefix-based, so an entry that covers a whole unallocated range blocks
every caller-id in it.

**Fix it by verifying the caller-id against what you own:**

1. Compare the rejected number against your **organization's DID list**
   (the numbers a trunk or dialer is allowed to present).
2. Where the integration passes an explicit allow-list
   (`allowedCallerIds`), compare against that list too — the reject is
   against either, depending on what the gate resolved first.
3. Present a verified number you own as the caller-id and retry once.

The reject is a 422 at origination time, before any SIP goes out. An
empty DNO list (the platform default) makes the check a cheap no-op, so
the block only fires where a populated entry matched.

## Per-country rate window limited<a id="voice-country-rate-limited" />

`429 VOICE_COUNTRY_RATE_LIMITED` fires when outbound voice to one
destination country exceeds its per-country sliding-window cap. The
guard weights the current minute and the tail of the previous minute,
so a burst concentrated on one high-cost country trips it even when no
single call looked excessive.

The 429 body names the country and the per-minute **limit**, e.g.
`{ "limit": 60, "country": "GB", "window": "1m" }`.

**Fix it by smoothing the send, not by retrying harder:**

* The guard **slides** rather than hard-blocks, so pacing the outbound
  over time clears it without a config change.
* Where the burst is real, scope the destination allow-list down to the
  countries you expect to dial — the voice-fraud guard works against a
  narrower window per country, and a leak guard reads the pattern
  against a far tighter focus than a country-wide sweep allows.

Unlike the auto-block sweep, this block is not destination-specific —
it is a country-scoped window, and the rejected call can dial again as
soon as the window rolls over. A campaign that keeps the country pinned
at `limit` just re-trips on every attempt, so the pause-then-distribute
loop is the fix, not retry-in-place.

## Trunk caller-id rejected<a id="voice-caller-id-rejected" />

`VOICE_CALLER_ID_REJECTED` fires on the **customer SIP trunk** path, when
the INVITE carries a caller-id that lands outside the trunk's own
allow-list and outside the org's DID list. The trunk accepts INVITEs
only where the calling-party number is one you have explicitly listed,
or — where the allow-list is empty — a DID the org owns.

**Fix it at the trunk**:

1. If the trunk carries an `allowedCallerIds` list, verify the rejected
   caller-id is *in* it — add it as a normalized E.164 entry, or present
   a listed one instead.
2. If the allow-list is empty, the gate falls back to the org DID list —
   present a DID the organization owns.
3. The gate normalizes the caller-id and the stored list entries with
   the same canonicalizer, so a bare-digit or access-prefixed entry
   still compares apples to apples — when it still mismatches, the
   entry itself is missing, not the format.

The reject is a 403 on the INVITE, before the call joins any other gate.

## What to capture before escalating

Work the matrix above first. If a block still misreads — the destination
is genuinely not an emergency code, the caller-id genuinely is on your
DID list, or the rate window keeps tripping well under its limit — open
a ticket with:

1. **The full error body** — the code, message, and the `details`
   object (per-code fields above).
2. **The destination and the presented caller-id**, E.164 normalized.
3. **The call path** — campaign/dialer origination, ad-hoc dashboard
   dial, or customer-trunk INVITE.
4. **Your organization ID** (Settings → Organization, or
   `organizationId` from `GET /api/v1/me`).

## What not to do

* **Do not retry in a loop.** Every pre-flight gate re-fires on every
  attempt; only the rate-window code clears on its own.
* **Do not reconfigure the trunk or codec.** The block fires before SIP.
* **Do not broaden the caller-id to "any number you can dial."** The
  DNO and trunk gates exist to keep you on numbers you can prove you
  own.
* **Do not reclassify an auto-block as one of these codes.** The
  per-destination auto-blocks fire on a different path (the
  detector sweep, not the pre-flight gate) and expire on their own —
  read them on
  [Voice destination auto-blocks](/compliance/voice-destination-auto-blocks).

## See also

* [Voice destination auto-blocks](/compliance/voice-destination-auto-blocks) —
  the detector-sweep per-destination blocks that fire *after* these
  pre-flight gates.
* [Troubleshooting: voice call quality](/troubleshooting/voice-call-quality) —
  the next page once a call *does* dispatch and the complaint is audio.
* [Troubleshooting: resolve dialing-window blocked calls](/troubleshooting/tcpa-window-blocked-calls) —
  the TCPA quiet-hours gate that rejects by recipient-local time.
* [References: error codes](/reference/error-codes) — the error catalog
  this page triages.
