Freeze one INVITE transaction and its first final response
Record the timestamp, Call-ID, branch, incoming PJSIP channel, dialplan context and extension, matched condition, requested cause, every provisional response and the first final response. Classify the symptom as unavailable application, invalid cause, wrong channel, unexpected final code, 200 already sent, upstream rewrite or caller behavior different from policy.
Do not begin by changing cause mappings or adding repeated hangups. RFC 3261 transaction evidence and the first final response define the response boundary for the INVITE.
Verify the installed maintenance release and active path
Confirm that the running release meets 18.21.0, 20.6.0 or 21.1.0 as applicable and that the loaded dialplan contains the expected application call. Follow the actual executed priorities rather than the source file alone.
On a managed FreePBX system, identify the generated or custom owner before editing. A successful reload is not proof that the call entered the expected context, and an application documented online is not proof that an older package exposes it.
Prove that execution is on the incoming PJSIP channel
Capture the channel technology, name, unique ID and linked ID at the application boundary. PJSIPHangup() is documented for the incoming PJSIP channel. If execution has moved to a Local channel, outbound callee or another bridge leg, the requested final response may not own the original INVITE transaction.
Correlate channel identifiers without treating the linked ID as permission to substitute one leg for another. Fix the dialplan placement rather than reaching across unrelated channels.
Locate the action that sent 200 or another final response first
Walk backward from the first final response to the responsible application or module. Check explicit Answer(), Playback() without noanswer, queue or conference admission, voicemail, media applications and any helper that answers implicitly. A later PJSIPHangup() cannot replace that final result.
If only 1xx responses preceded the call, keep them distinct from the final response. If an intermediary rewrote the final code, retain the Asterisk-side and caller-side messages as separate observations.
Compare requested response, wire code and translated cause
Confirm that the requested numeric value is in the documented 400 through 699 range or that the symbolic name is supported by the installed PJSIP definitions. Compare that input with Asterisk logs, the captured final response and per-channel tech and ast causes.
The published mapping is many-to-one. A translated busy, rejected, unavailable or interworking cause is not sufficient to reconstruct the exact response or the leg that produced it. Preserve every called-channel result when Dial() created multiple legs.
Correct one owner and repeat negative and allowed controls
Correct only the demonstrated issue: version, loaded path, channel ownership, condition, cause value, implicit answer, upstream rewrite or caller policy. Keep the previous dialplan and a rollback. Avoid globally replacing Hangup() or remapping every cause to make one trace look uniform.
Repeat the rejected scenario and a permitted-call control. Acceptance requires the intended first final response on the original transaction, expected translated cause where relevant, correct caller behavior and no unintended answer. No PBX, module, dialplan, channel, response, cause, packet, endpoint, trunk or call was inspected or tested for this diagnostic.
Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- Asterisk PJSIPHangup dialplan application ↗
- Asterisk Hangup dialplan application ↗
- Asterisk hangup-cause inspection guide ↗
- Asterisk hangup-cause mappings ↗
- RFC 3261: SIP response and transaction semantics ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.