Howwise RSS
VoIP & Phone Systems8 min read

Asterisk IVR Multiple Digits: Fix Dropped Extension Dialing

Short answer

Asterisk IVR multiple digits fail when the entry matches no extension in the IVR context: Direct Dial only knows local extensions, so a remote CUCM number like 291 hits the invalid handler. Add a pattern such as _2XX that dials the trunk.

Key takeaways
  • FreePBX Direct Dial only matches extensions that exist in FreePBX, so numbers on CUCM or 3CX are invalid and fall to the i handler.
  • A pattern like _2XX added to the ivr-N context, dialing PJSIP/${EXTEN}@trunk, makes remote extensions reachable with no placeholders.
  • Single-digit options sharing a first digit with extensions (option 2 and 2XX) cause delays or intercepted entries, so remove or renumber them.
  • Set the Timeout and Invalid destinations to an operator or the IVR itself, never Hangup, so a mistyped entry does not drop the caller.
  • Confirm with dialplan show ivr-1, pjsip set logger on and CUCM route patterns to find which side rejects the call.

Why does the IVR drop the call when callers dial more than one digit?

An Asterisk IVR is a loop of Background() (play the prompt while listening for DTMF) followed by WaitExten(). Each digit is appended to the buffer and Asterisk searches the IVR context for a matching extension. If the buffer matches exactly and nothing longer could match, it executes immediately. That is why a single digit like 1 works instantly.

For 291 to work, the context needs an extension that matches 291. FreePBX Direct Dial (Enable Direct Dial in the IVR) just includes the context from-did-direct-ivr, which holds entries only for extensions that exist in FreePBX. Extensions living on CUCM or 3CX are not there, so 291 matches nothing.

When nothing matches, Asterisk jumps to the i (invalid) extension. If the IVR's invalid retries are exhausted or the invalid destination is Hangup, the caller is disconnected. If digits stop arriving, the t (timeout) extension fires the same way. To the caller it feels like the call dropped right after typing the extension.

How does Asterisk match digits: patterns, X, Z, N and the dot

Dialplan patterns start with an underscore. The character classes are fixed, and knowing them lets you cover whole ranges in one line.

The difference between . and ! matters in an IVR. The dot needs at least one more character and keeps matching as long as digits arrive, so _2. waits for the digit timeout. The ! wildcard matches zero or more characters and counts as a complete match as soon as it is unambiguous, which is useful for variable-length numbers but can fire early. For fixed-length internal extensions, prefer explicit patterns.

PatternMatchesTypical use
XOne digit 0-9_2XX = 200 to 299
ZOne digit 1-9_ZXX = 3-digit, no leading 0
NOne digit 2-9_NXXX = 4-digit, first digit 2-9
[135-7]Any listed digit or range_[23]XX = 200-399
. (dot)One or more of any character_9. = trunk prefix, any length
! (bang)Zero or more, matches earlyVariable-length, use with care

Which fix should I use for extensions on another PBX?

There are three workable approaches. All of them end with the IVR context having something to match; they differ in how much you maintain.

For a CUCM or 3CX range that is contiguous (say 2000 to 2999 or 200 to 299), the pattern approach is almost always the best choice. Placeholders only make sense for a handful of numbers.

FixHow it worksBest whenDrawback
1. Placeholder or custom extensionsCreate a local extension or Custom Extension per remote number, forwarding or dialing out to the real numberFew remote numbersOne object per number; must stay in sync with CUCM
2. Pattern in extensions_custom.conf_2XX added to the ivr-N context dials the CUCM trunkContiguous ranges, many numbersHand-written dialplan; no GUI validation
3. Include a custom context into ivr-Nivr-N includes your own context holding patternsReusing one range across several IVRsContext names and hooks vary by version
Tip: After any change, run dialplan show from-did-direct-ivr and dialplan show ivr-1 to confirm what actually exists. Context names and generated hooks differ between FreePBX versions, so trust the live dialplan over memory.

Copy-paste dialplan for Asterisk IVR multiple digits (pattern-based extension dialing)

Asterisk merges multiple definitions of the same context name, so you can add lines to [ivr-1] from extensions_custom.conf, which FreePBX never overwrites. Replace 1 with your IVR's ID and cucm-trunk with the actual trunk name (the PJSIP endpoint name shown by pjsip show endpoints).

Dialing the trunk directly skips outbound routes and their dial patterns. Dialing Local/${EXTEN}@from-internal instead sends the call through outbound routes, which is useful when you want route permissions, prefixes or failover to apply.

; /etc/asterisk/extensions_custom.conf

[ivr-cucm-ext]
exten => _2XX,1,NoOp(IVR remote ext ${EXTEN} from ${CALLERID(num)})
 same => n,Set(CALLERID(dnid)=${EXTEN})
 same => n,Dial(PJSIP/${EXTEN}@cucm-trunk,45,Tt)
 same => n,Goto(app-operator,s,1)   ; fallback if unanswered/failed (use your own destination)

; Alternative: go through outbound routes
;exten => _2XX,1,Dial(Local/${EXTEN}@from-internal,45)

; Hook into IVR 1 (merged with the generated context)
[ivr-1]
include => ivr-cucm-ext
Warning: Reload with 'dialplan reload' only in a quiet period and test on a lab IVR first. A broad pattern such as _X. in an IVR context can swallow the i and t handling for legitimate entries and lets callers dial arbitrary numbers through your trunk, which is a toll fraud risk. Keep patterns as narrow as the real extension range.

Why do timeouts and single-digit options break multi-digit entry?

Two timers matter. TIMEOUT(response) is how long Asterisk waits for the first digit after the prompt, and the IVR's Timeout field controls this. TIMEOUT(digit) is the gap allowed between digits and is typically only a few seconds by default. A long digit timeout makes callers wait in silence after typing a complete 3-digit number if a longer match is still possible. A short one cuts off slow typists mid-entry, which then falls to i.

The prefix conflict is the most common hidden cause. If the menu has an option 2 and your extensions are 2XX, then 2 is a complete match but also the start of a longer pattern. Depending on version and settings, the caller either waits for the digit timeout before option 2 fires, or the option fires before the rest is dialed. Either way 291 becomes unreliable.

Fix it by renumbering options (use 1 for sales, 9 for operator, and keep extensions in another range) or by moving the extension range away from the option digits. Callers pressing # to finish an entry also fail, because # is not part of _2XX. Either tell callers not to press it or add an explicit pattern such as _2XX# if you want to support it.

How do I stop callers from being dropped?

In the IVR settings, set the Timeout destination and the Invalid destination to the operator, a ring group or the same IVR rather than Terminate Call/Hangup. Set Invalid Retries to 2 or 3 and enable Invalid Retry Recording so callers hear a message such as 'that extension was not recognized' before the retry. Use the same pattern for Timeout Retries.

Also give the Dial() a fallback line after it, as in the dialplan above. If CUCM returns 404 or busy, Dial() ends and the call would otherwise hang up at the end of the context.

Debugging checklist with the Asterisk CLI

Work from the caller inward: did the digits arrive, did they match, did the INVITE go out, and what did CUCM answer. A failure at each stage looks different.

Symptom in the CLILikely causeFix
Sent to 'i' handler / Invalid extensionNo pattern matched the entered digitsAdd the _2XX pattern or placeholder; check prefix conflicts
Only the first digit ever appearsDTMF not received after the first or mismatch (RFC2833 vs inband)Set dtmf_mode=rfc4733 on the inbound trunk/endpoint, match the carrier
Executing 't' after typingDigit timeout too short or typing too slowRaise TIMEOUT(digit) slightly; do not exceed about 5 seconds
INVITE sent, 404 Not FoundCUCM has no route pattern for the numberAdd the route pattern or translation on CUCM
INVITE sent, 403 or 488Calling search space blocks it or codec mismatchFix CSS/partition; align codecs (ulaw/alaw) on both sides
No INVITE at allWrong trunk name or outbound route not reachedCheck pjsip show endpoints and the Dial() string
  1. Run asterisk -rvvvvv (or core set verbose 5 inside the CLI) and place a test call.
  2. Watch for lines like 'Goto (ivr-1,i,1)', which confirms the digits matched nothing.
  3. Run dialplan show ivr-1 and confirm your _2XX pattern is listed.
  4. Run pjsip set logger on and repeat the call to see the outbound INVITE and the response from CUCM; sngrep shows the same flow more readably.
  5. Run rtp set debug on if the call connects but audio is missing, and check direct_media, external_media_address and local_net on the trunk.
asterisk -rvvvvv
dialplan show ivr-1
dialplan show from-did-direct-ivr
pjsip show endpoints
pjsip set logger on
rtp set debug on
# separate shell:
sngrep -d any port 5060

What must be configured on the CUCM side?

Asterisk can only deliver the digits it sends, so CUCM must accept them. The SIP trunk's calling search space must contain a partition holding a route pattern or directory number that matches what you send. If the IVR passes 291 but CUCM expects 5 digits, add a translation pattern or send the full number from the dialplan with a prefix.

On the Asterisk side, confirm the trunk allows the pattern. If you use Local/${EXTEN}@from-internal, an outbound route must match the digits, otherwise you get 'No such extension' in from-internal rather than an INVITE.

Common questions

Why does FreePBX IVR Direct Dial not work for extensions on another server?

Direct Dial includes only extensions that exist in FreePBX itself. Remote numbers are unknown to it, so you must add a pattern route, custom extensions or placeholders for them.

Can I use 3-digit extension dialing from an IVR to an external PBX?

Yes. Add a pattern such as _2XX to the ivr-N context that dials the trunk with Dial(PJSIP/${EXTEN}@trunkname). Make sure the remote PBX has a matching route pattern or directory number.

What do the i and t extensions do in an Asterisk IVR?

The i extension runs when the entered digits match no extension, and t runs when the caller enters nothing before the timeout. In FreePBX these are mapped to the invalid and timeout settings and their retry counts.

How long should the digit timeout be for extension entry?

Around 3 to 5 seconds between digits suits most callers. Shorter values cut off slow typing and longer ones leave callers in silence after a complete entry.

Will my changes in extensions_custom.conf survive a FreePBX reload?

Yes. FreePBX regenerates its own files but leaves extensions_custom.conf untouched. Only the generated contexts are rewritten, so keep your additions in your own context and include it.

Related topics:asteriskfreepbxivrdialplancucm