Skip to main content

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_url pointer to the emergency-calling page 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

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

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

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.

See also