Gosub()
"Gosub attempted to reach non-existent destination" in Asterisk
Gosub failures are more confusing than Goto failures because the Gosub is often one you did not write. Dial() and Queue() call subroutines implicitly, and when those targets are missing the error names a destination you have never typed.
What it looks like in the log
[2026-08-17 14:22:09] ERROR[16601][C-00001d40] app_stack.c: Gosub attempted to reach non-existent destination 'macro-answer,s-ANSWER,1'
What it means
Gosub() is a call to a dialplan subroutine that returns when it hits Return(). Like Goto, it needs a context, extension and priority that all exist. Unlike Goto, it is frequently invoked on your behalf.
The U() option on Dial() runs a subroutine when the call is answered. The b() option runs one before the outbound leg is created. Queue() has equivalents. Each of them builds a target name from the option you supplied plus a suffix Asterisk chooses - which is where s-ANSWER comes from, and why searching your dialplan for that string finds nothing.
Most common causes
-
01A macro or subroutine that was renamed or removed
The most common cause. The context named in the U() or b() option no longer exists under that name.
-
02The s-ANSWER pattern from Dial()'s U() option
Dial() appends the status to the subroutine name. If the target context does not define an
s-ANSWERextension, the answer handler fails even though the context itself exists. -
03A migration from Macro() to Gosub()
Converting old macro-based dialplans leaves references in one style pointing at contexts defined in the other. The names are close enough to look correct.
-
04A missing priority rather than a missing extension
The target extension exists but not at priority 1, which the error reports identically.
-
05A subroutine in a file that is no longer included
Splitting the dialplan across files and forgetting one
#includemakes a whole set of subroutines vanish at once.
How to tell which one it is
Read the full destination in the error - it is printed as context,extension,priority. Then check each of the three separately. Very often the context exists and the extension does not, which points at the implicit-suffix case rather than at a typo.
If the extension name ends in a status word like -ANSWER, the call came from a Dial() or Queue() option. Find the option in the dialplan and check what context name it supplies.
How to fix it
-
Define the s-ANSWER extension in the target context
If Dial() is calling an answer subroutine, the context it names must contain an
s-ANSWERextension, even if it only does a NoOp and returns. -
Update the U() or b() option to the current context name
Where the subroutine was renamed, fix the reference in the Dial options rather than recreating the old context.
-
Check the priority exists
The target needs priority 1 specifically unless another is named. An extension starting at a different priority fails identically.
-
Confirm all dialplan includes are present
A missing include produces a large number of these at once, which is a useful signal that the problem is structural rather than a single typo.