VoIP.info Diagnostic

Asterisk PJSIP required outbound header is missing or duplicated

Trace one outbound request through the caller, callee, handler and header store before changing a trunk or copying inbound data.

Reviewed 2026-10-13Current Asterisk PJSIP header, inheritable-header, header-list, header-parameter, response-header and pre-dial-handler documentation reviewed October 8, 2026; PJSIP_INHERITABLE_HEADER is documented from 20.19.0, 22.9.0 and 23.3.0, and no PBX, dialplan, channel, header, provider, endpoint, request, response, registration, authentication exchange, availability, compatibility or call was inspected or testedAdvancedDocumentation based · not lab tested

Freeze one failed transaction

Record the timestamp, dialed digits, selected trunk or endpoint, SIP method, destination, Call-ID, expected header name and expected value source. Save the peer's exact response and a sanitized working transaction if one exists. State whether the header is absent, duplicated, malformed, attached to the wrong method or present but ignored.

Do not start by adding the header in several contexts. One provider rejection can reflect routing, authentication, identity policy or message syntax even when its reason phrase mentions a header.

Map caller and callee channels

Follow the dialplan from the incoming or originating channel through Local channels, Queue or FollowMe paths and the final outbound PJSIP callee. Identify where the value is created, which channel owns it, and when the outbound channel comes into existence. A normal-context PJSIP_HEADER() call commonly targets the caller rather than the callee that sends the INVITE.

Inspect the active dialplan and one bounded verbose trace. In a FreePBX system, retain the GUI or module owner and the supported custom hook; a generated file that happens to contain the handler is not the source of truth.

Identify the header store and version boundary

If the design uses PJSIP_HEADER(), prove that a lowercase b pre-dial handler ran on each intended outbound channel and returned. If it uses PJSIP_INHERITABLE_HEADER(), confirm Asterisk is at least 20.19.0, 22.9.0 or 23.3.0 on the corresponding branch and prove the header was set before child creation.

Do not update or remove an inheritable header with PJSIP_HEADER(), or a direct header with PJSIP_INHERITABLE_HEADER(). The documented stores are separate. If both added the same name, remove the demonstrated duplicate through its owning function rather than clearing every custom header.

Check action semantics and message phase

add creates another instance. update requires the named instance to exist. remove affects headers previously added by the same function and can use a prefix match. Preserve the operation result, header number and value before retrying. Confirm that a From URI parameter is not being treated as a standalone header; PJSIP_HEADER_PARAM() currently supports parameters on From only.

If the missing evidence is in a 200 response, use the response-header path on the outbound channel at pre-connect time. PJSIP_HEADERS() enumerates names from an inbound INVITE and cannot prove what Asterisk emitted on the opposite leg.

Prove the smallest correction on and off target

Correct only the demonstrated owner: move the direct write to a callee pre-dial handler, add the required Return(), set an inheritable header before child creation on a supported version, remove one duplicate, or correct one provider-defined value. Preserve the prior dialplan and loaded state.

Repeat the failed call, verify the exact outbound request, response, answer and media separately, then run an unrelated route that must not receive the header. Remove captures and temporary logging. Do not forward arbitrary inbound headers, reusable tokens or asserted identities across trust boundaries. No PBX, dialplan, header, provider, endpoint or call was tested for this diagnostic.

Check the Gosub frame and handler channel before changing the header

The Gosub diagnostic distinguishes ordinary, caller pre-dial, callee pre-dial and pre-bridge execution. A correct subroutine log on the caller is not proof that the outbound PJSIP channel received the header.

Diagnose a missing From parameter separately

When the header exists but one From parameter is absent or in the wrong location, use the parameter diagnostic before replacing the whole header.

Diagnose inheritance before adding a second header copy

When a required field should propagate from a calling channel, follow the inheritable-header diagnostic before adding the same name through PJSIP_HEADER().

Do not confuse an inbound list with an outbound header

If the evidence comes from PJSIP_HEADERS(), use the inbound list diagnostic. A correct inbound inventory does not prove the callee INVITE carried a required field.

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.