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 — 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.Emergency short 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_urlpointer to the emergency-calling page on every block, so a branch on the error code can surface the disclaimer verbatim.
Do-Not-Originate caller-id 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:
- Compare the rejected number against your organization’s DID list (the numbers a trunk or dialer is allowed to present).
- 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. - Present a verified number you own as the caller-id and retry once.
Per-country rate window 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.
limit just re-trips on every attempt, so the pause-then-distribute
loop is the fix, not retry-in-place.
Trunk 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:
- If the trunk carries an
allowedCallerIdslist, verify the rejected caller-id is in it — add it as a normalized E.164 entry, or present a listed one instead. - If the allow-list is empty, the gate falls back to the org DID list — present a DID the organization owns.
- 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.
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:- The full error body — the code, message, and the
detailsobject (per-code fields above). - The destination and the presented caller-id, E.164 normalized.
- The call path — campaign/dialer origination, ad-hoc dashboard dial, or customer-trunk INVITE.
- Your organization ID (Settings → Organization, or
organizationIdfromGET /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.
See also
- Voice destination auto-blocks — the detector-sweep per-destination blocks that fire after these pre-flight gates.
- Troubleshooting: voice call quality — the next page once a call does dispatch and the complaint is audio.
- Troubleshooting: resolve dialing-window blocked calls — the TCPA quiet-hours gate that rejects by recipient-local time.
- References: error codes — the error catalog this page triages.