Separate existence, evaluation and execution
DIALPLAN_EXISTS(), EVAL_EXTEN() and EVAL_SUB() answer different questions. The first checks whether an exact context, extension and priority exists. The second evaluates the application data at a target and returns a string without executing that application. The third runs a Gosub location and returns the value supplied by Return().
Choose the least powerful primitive that meets the requirement. A successful existence check does not prove that normal pattern or include resolution would select that target, that evaluating it is safe, or that a later destination will succeed.
Check the exact target before reading a value
DIALPLAN_EXISTS(context,extension,priority) returns 1 when that exact dialplan target exists and 0 otherwise. Log the bounded context, extension and priority as separate fields and branch on existence before interpreting a returned value.
Keep missing target distinct from a target whose evaluated value is empty. Treat context, extension and priority as control data: map external input to an allow-listed internal name instead of inserting caller-controlled text directly into a dynamic lookup.
Use EVAL_EXTEN for Return data, not application execution
EVAL_EXTEN() looks up a context, extension and priority, evaluates the target application data and returns the result as a string. The target application itself is not executed. In the documented pattern, the target is a Return(...) entry used as a lookup table or function-like value.
Variable and function references are resolved in the target extension context. In particular, ${EXTEN} refers to the extension supplied to EVAL_EXTEN(), not the caller extension. Record both caller and target values when troubleshooting a surprising result.
Reserve EVAL_SUB for logic and arguments
EVAL_EXTEN() cannot pass Gosub arguments. EVAL_SUB() can call a Gosub location with optional arguments and return the value passed to Return(), so it is the appropriate primitive only when real dialplan logic is required. Its documented availability begins in specific maintained branch releases rather than every historical Asterisk version.
Keep the routine short, bounded and independent of channel interaction. The documentation permits arbitrary dialplan, including blocking work, but does not recommend it; a function call hidden inside another expression should not become an unbounded workflow.
Make evaluation-time effects explicit
Function expressions can be evaluated while Asterisk parses application arguments. A routine with writes, network calls, blocking operations or channel mutations can therefore run earlier, more often or in a different branch than an operator expects. Do not call a side-effecting EVAL_SUB() more than once merely to log and then use its result.
Assign the result once, preserve an invocation identifier and branch on the stored value. Keep a side-effect-free control routine for testing. The documented guarantee that EVAL_SUB() returns even if the channel hangs up describes function control flow; it does not prove a live channel, completed side effect or successful call.
Test version, target, return and outcome separately
In an authorized staging context, record the running Asterisk branch, loaded function availability, exact target, DIALPLAN_EXISTS() result, caller and target extension values, arguments, returned string, invocation count and next executed priority. Exercise an existing non-empty return, an existing empty return, a missing target and one bounded EVAL_SUB() routine with no external effects.
Then validate the downstream branch separately and confirm an unrelated control route is unchanged. Remove temporary diagnostics after acceptance. No PBX, module set, dialplan, channel, lookup, subroutine, side effect or live call was tested for this guide.
Keep evaluated dialplan data separate from external database state
The func_odbc guide covers external ODBC query execution, escaping, row cardinality and latency rather than treating it as another dialplan-text lookup.
Keep polled expressions cheap and side-effect free
The WaitForCondition guide treats every function in the condition as repeated work and keeps lookup outcome separate from state ownership.
Confirm which loaded route actually won
The AMI dialplan diagnostic reconstructs context, digits, caller ID, exact matches, patterns, includes and switches before evaluating execution.
Validate a dynamic lookup result once
Use the dialplan input guide to store and validate the returned value before any later dynamic target or branch.
Keep legacy-name migration inside the lookup boundary
The VALID_EXTEN migration guide makes context, extension and priority or label explicit before DIALPLAN_EXISTS() is evaluated.
Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- Asterisk 23 DIALPLAN_EXISTS function ↗
- Asterisk 23 EVAL_EXTEN function ↗
- Asterisk 23 EVAL_SUB function ↗
- Asterisk 23 Return application ↗
- Asterisk Configuring res_odbc ↗
- Asterisk func_odbc.conf sample ↗
- Asterisk res_odbc.conf sample ↗
- Asterisk 23 ODBC_FETCH function ↗
- Asterisk 23 SQL_ESC function ↗
- Asterisk 23 SQL_ESC_BACKSLASHES function ↗
- Asterisk security advisory AST-2022-003 ↗
- Asterisk 23 WaitForCondition application ↗
- Asterisk 22 WaitForCondition application ↗
- Asterisk dialplan expressions ↗
- Asterisk conditional applications ↗
- Asterisk 23 VARIABLE_EXISTS function ↗
- Asterisk 23 GLOBAL_EXISTS function ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- ↗
- Asterisk FILTER dialplan function ↗
- Asterisk REGEX dialplan function ↗
- Asterisk ISNULL dialplan function ↗
- Asterisk LEN dialplan function ↗
- Asterisk FIELDQTY dialplan function ↗
- Asterisk CUT dialplan function ↗
- Asterisk dialplan-functions overview ↗
- Asterisk func_strings implementation ↗
- Asterisk 22 VALID_EXTEN function and deprecation notice ↗
- Asterisk 23 dialplan-function index ↗
- Asterisk func_dialplan implementation ↗
- Asterisk CLI syntax and function-help commands ↗
- Asterisk dialplan reload and show workflow ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.