VoIP.info Troubleshooting

FreePBX custom destination fails, loops or returns wrong: target, stack and branch proof

Trace one call through the selecting module, saved target, generated wrapper, loaded context and runtime Goto or Gosub/Return outcome.

Reviewed 2026-10-14Sangoma PBX GUI 13 Custom Destinations and Misc Applications guides, FreePBX Custom Applications Registry release/17.0 metadata version 17.0.1 and current dialplan source, and current Asterisk Goto, Gosub, Return and dialplan documentation reviewed October 10, 2026; no PBX, module, database row, custom code, generated or loaded dialplan, channel, stack, downstream application or call was inspected or testedAdvancedDocumentation based · not lab tested

Freeze one attempt and name the visible symptom

Record the timestamp and timezone, Asterisk linked identifier, ingress or originating extension, selecting FreePBX module and branch, saved target, Return setting, configured return destination and observed result. Classify whether the destination is absent from a selector, the call stops immediately, reaches the wrong place, loops, never returns, returns to the wrong branch or works only from one entry point.

Preserve one known-good managed destination selected by the same module when safe. Do not edit custom code, toggle Return or redirect the route before this baseline is captured; each changes a different control-flow boundary.

Prove the selector chose the exact registry entry

Start with the route, IVR, queue or other module that should select the Custom Destination. Verify its saved destination identifier and the registry row’s current description, target, Return flag and return destination. A destination that appears in a dropdown is only a registry result, while a GUI test that saves successfully is not proof that the live call selected it.

Correlate the bounded call with the generated branch and first application after selection. If the caller matched another inbound route, IVR option, timeout, invalid branch or schedule, stay at the selector rather than debugging custom code.

Prove the parsed target exists in the loaded dialplan

Expand the saved [context],[extension],[priority] into three exact values and inspect the generated destination. Then verify the owning custom source is included and the target exists in the loaded dialplan on the node that handled the call. Compare exact extensions, patterns, includes and priorities; do not infer reachability from a source filename or GUI description.

Asterisk documents that Goto changes the current context, extension and priority. If the requested location is invalid it tries the i and then h extensions where available and otherwise terminates the channel. Capture that transition instead of labeling every immediate hangup an application failure.

Separate direct transfer from the Gosub and Return stack

Current FreePBX release/17.0 source generates a direct Goto to the target when Return is disabled. When Return is enabled, it exposes a wrapper that calls the target with Gosub, logs the return point and then uses Goto for the chosen return destination. Compare the saved flag with the generated and loaded path; do not assume the description reveals the mode.

For return mode, follow every custom-code branch to an Asterisk Return and check for recursion back into the same wrapper. For direct mode, do not expect execution to resume at the selecting module. Stack errors, a missing Return, unintended fall-through or a return destination that reselects the wrapper can explain stops and loops without changing the target address.

Follow the custom application and downstream boundary

Once control reaches the target, trace the exact application result, variables and downstream destination. Keep dialplan selection separate from AGI, shell command, API, database, file, permission, trunk or endpoint failures. Capture exit status and bounded error evidence without enabling indiscriminate debug logging or placing secrets and caller data into tickets.

Review execution identity, input validation, command construction, network allowlists and calling permissions before broadening access. A command that succeeds manually as an administrator is not proof that Asterisk can execute it safely, and a downstream call attempt is not proof that the intended party answered.

Repair the smallest owner and retest both control paths

Correct only the demonstrated boundary: selector, saved target, Return flag, return destination, include, context, extension, priority, missing Return, recursion guard, application dependency or downstream route. Submit and Apply Config through FreePBX when managed state changes, then prove the generated and loaded dialplan agree; do not make a generated file the durable fix.

Retest the original success path, invalid input or application error, timeout where relevant, the configured return branch or deliberate direct transfer, loop guard and an unaffected managed destination. Preserve rollback and remove temporary logging. No PBX, custom destination, dialplan, application, security control, downstream service or call was inspected or tested for this guide.

Check for an obsolete Macro target after a FreePBX 17 restore

When the failure begins during a FreePBX 17 migration, the restored custom-macro diagnostic verifies restored files, loaded includes, unavailable Macro calls and the converted Gosub stack before changing the destination string repeatedly.

Sources & applicability

Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.

Examples require adaptation to your topology. No live PBX or hardware testing is claimed.