Name the value, owner and moment it disappears
Preserve one authorized call and record the variable, Dial() option, CDR field or channel-scoped feature that appears to vanish. Capture the timestamp, originating channel, both Local halves, eventual destination, exact dial string, where the value was set, where it was read, and whether the read occurred before answer, after answer, after bridge creation or at hangup.
A value visible on Local/...;1 or Local/...;2 is not automatically present on the original caller or final destination. Likewise, an absent Local channel after answer can be the expected optimization lifecycle. Do not add inheritance prefixes or /n until the missing value's intended surviving owner is explicit.
Prove optimization before treating disappearance as failure
By default, a Local channel attempts to optimize itself out after the destination answers. Asterisk documents that variables, dialplan state and Dial() options associated with that Local layer are destroyed with it. Correlate LocalOptimizationBegin and LocalOptimizationEnd with the two Local names and the resulting bridge changes. A post-answer read against a removed Local name is not evidence that Asterisk lost a value from a surviving channel.
Compare the symptom boundary with a no-answer control. If the value remains while the Local pair remains and disappears when optimization completes, channel ownership is the leading explanation. If it is absent before optimization, inspect creation, spelling, scope and inheritance instead. Keep optimization, hangup and a later report query as separate events.
Separate inheritance from Local-channel retention
A single leading underscore makes a channel variable inherit to the next child channel and removes that prefix on the child; it does not continue indefinitely. A double leading underscore remains on descendant channels and continues to inherit. Asterisk also notes that setting any prefixed or unprefixed form replaces the other forms of the same variable.
Inheritance controls copying when child channels are created. /n controls whether the Local pair later optimizes away. They solve different problems: a correctly inherited value can outlive the Local layer on the intended child, while retaining the pair does not retroactively copy a value to another channel. Map each child creation and inspect the value there instead of adding underscores until one output appears.
Put data directly on the caller or callee that needs it
Asterisk pre-dial handlers run after Dial() is invoked but before the call is placed. The uppercase B option runs on the caller before callee channels are created; lowercase b runs on each created callee before dialing it. Both are Gosub-based and must return, and the documentation warns against actions that move those channels into other applications.
Use a short pre-dial handler when the requirement is to set data on the actual caller or each actual callee, rather than on an optimizing Local intermediary. Confirm the installed application's option syntax and loaded handler. Then read the value from the same channel after answer. Do not copy secrets or unbounded personal data through inherited variables merely to make debugging easier.
Use /n only for behavior that must live on the Local pair
The /n no-release modifier keeps the Local pair in the call path. Asterisk's optimization example uses it when a Dial() time-limit option is owned by the Local channel and would otherwise be removed. That is a bounded channel-lifetime requirement, not a universal cure for caller ID, CDR fields, queue metadata or downstream reporting.
Before using /n, write the acceptance statement: which Local half owns the behavior, why it cannot be placed on a surviving channel, and what must remain after answer. Re-test bridge membership, media, transfer, hold, feature operation, hangup and cleanup. Retention adds a channel layer and performance cost, so remove it if the named behavior can be owned correctly elsewhere.
Treat CDR data as a separate placement problem
Asterisk's CDR specification explicitly says properties set on optimized Local channels are not propagated. When optimization occurs, the Local CDRs are finalized and new records can be generated for the channels in the merged bridge. Adding /n solely to preserve a reporting field can therefore change the call topology instead of fixing the field's owner.
Use a pre-dial handler to set CDR data on the appropriate channel at creation, then correlate uniqueid, linkedid, sequence, Party A and Party B through finalization, dispatch, backend storage and the report query. A field visible in the dialplan is not proof that a particular finalized CDR or dashboard row contains it.
Retest the smallest correction and preserve rollback
Choose one correction supported by the evidence: set the value on the surviving channel, use the required inheritance depth, correct a misspelled or overwritten variable, place caller or callee data in the appropriate pre-dial handler, retain the Local pair for a named channel-scoped feature, or fix downstream correlation. Preserve the original dialplan and loaded state before reloading.
Repeat answer, no answer, busy and cancellation, then transfer, hold and hangup only where relevant. Confirm the value on its intended owner before and after answer, the expected optimization or retained pair, bridge and media behavior, cleanup and record output. Roll back if an unaffected route or feature regresses. No PBX, channel, variable, handler, CDR, bridge, event, endpoint, media path or live call was inspected or tested for this guide.
Separate a channel variable from an outbound SIP header
If the symptom is a provider-required header, use the focused PJSIP header diagnostic. It maps the caller, Local pair, final callee, handler and header store before changing optimization or inheritance.
Separate a missing Gosub return from Local optimization
When the problem begins before answer or on the wrong handler channel, use the Gosub diagnostic. Continue with Local-channel optimization only after both halves and the intended surviving data owner are identified.
Distinguish Local optimization from post-bridge routing
If an expected Local leg disappears or never reaches a target after answer, use the after-bridge diagnostic to separate optimization, bridge exit, owner survival and destination resolution.
Check whether the counted Local leg optimized away
When a group count changes at answer, use the channel-group workflow to identify both Local halves, membership and the surviving owner before adding /n.
Separate inheritance from Local optimization
The general variable diagnostic proves whether the value ever reached each child before deciding that Local optimization removed the required owner.
Separate Dial variables from Local-channel optimization
The Dial diagnostic identifies which channel ran Dial and which channel must retain a value after answer.
Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- Asterisk Local Channel overview ↗
- Asterisk Local Channel modifiers ↗
- Asterisk Local Channel optimization ↗
- Asterisk channel-variable inheritance ↗
- Asterisk pre-dial handlers ↗
- Asterisk CDR specification and Local Channel optimization ↗
- Asterisk AMI v2 Local Channel optimization events ↗
- Asterisk PJSIP_HEADER dialplan function ↗
- Asterisk PJSIP_INHERITABLE_HEADER dialplan function ↗
- Asterisk PJSIP_HEADERS dialplan function ↗
- Asterisk PJSIP_HEADER_PARAM dialplan function ↗
- Asterisk PJSIP_RESPONSE_HEADER dialplan function ↗
- Asterisk dialplan subroutines overview ↗
- Asterisk Gosub guide ↗
- Asterisk 22 Gosub application reference ↗
- Asterisk 22 Return application reference ↗
- Asterisk STACK_PEEK function reference ↗
- Asterisk pre-bridge handlers ↗
- Asterisk 22 Dial application reference ↗
- Asterisk 22 CHANNEL function reference ↗
- Asterisk 22 Bridge application reference ↗
- Asterisk 22 Goto application reference ↗
- Asterisk 22 BridgeEnter AMI event ↗
- Asterisk 22 BridgeLeave AMI event ↗
- Asterisk 22 Hangup AMI event ↗
- Asterisk GROUP function ↗
- Asterisk GROUP_COUNT function ↗
- Asterisk GROUP_LIST function ↗
- Asterisk GROUP_MATCH_COUNT function ↗
- Asterisk channels key concepts ↗
- Asterisk 22 Set application ↗
- Asterisk 22 MASTER_CHANNEL function ↗
- Asterisk 22 LOCAL function ↗
- Asterisk 22 LOCAL_PEEK function ↗
- Asterisk 22 VARIABLE_EXISTS function ↗
- Asterisk 22 IMPORT function ↗
- Asterisk 23 Dial application ↗
- Asterisk hangup-cause overview ↗
- Asterisk HANGUPCAUSE_KEYS function ↗
- Asterisk CHANNEL function ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.