Howwise RSS
VoIP & Phone Systems7 min read

SIP 488 Not Acceptable Here: Find the Rejected SDP Line

Short answer

SIP 488 Not Acceptable Here means the far end, or Asterisk itself, understood your INVITE but rejected the SDP offer: no common codec, an RTP/SAVP versus RTP/AVP mismatch, or a broken media line. Read the SDP in a capture to see which.

Key takeaways
  • A 488 is a media negotiation failure, not an authentication or routing failure, so the answer is always in the SDP body and the Warning header.
  • Compare the source IP of the 488 with your PBX and trunk addresses to learn whether the provider or Asterisk rejected the call.
  • The m= line profile (RTP/AVP vs RTP/SAVP) and the payload list after it identify encryption and codec mismatches in seconds.
  • Fix codecs on the trunk endpoint (disallow=all, then allow=ulaw,alaw) and set media_encryption to match what the provider accepts, then reload.
  • Verify with a fresh test call: the 200 OK SDP should list one codec plus telephone-event, and pjsip show channelstats should show RTP flowing both ways.

What does SIP 488 Not Acceptable Here mean?

A 488 is a 4xx client-error final response. The INVITE was parsed and the request itself is fine, but the session description (SDP) in it cannot be accepted. Authentication, routing and dialplan are not the problem, which is why the failure is usually instant: no ringing, no early media.

The response often carries a Warning header that tells you which part of the SDP failed. These codes come from the SIP specification and are the fastest clue:

Warning headerMeaningUsual cause
301 Incompatible network protocolTransport in the m= line not supportedOffering RTP/SAVP, UDPTL or another profile the far side lacks
302 Incompatible network address formatsAddress type not supportedIPv6 in c= line to an IPv4-only peer
304 Media type not availableMedia type not supportedVideo m= line, or T.38 image stream, rejected
305 Incompatible media formatNo codec in commonOffered payload list does not overlap the far side's list
306 Attribute not understoodAn a= line was refusedUnsupported crypto suite or odd attribute
307 Session description parameter not understoodOther SDP parameter refusedBad ptime, malformed c= line

How do I tell who sent the 488: the provider or Asterisk?

Look at the source IP of the 488 packet. If it comes from the trunk's IP, the provider rejected your offer. If the 488 is generated locally, it is sent from the PBX itself (or you see it on an internal leg), and the Asterisk log typically contains messages about no compatible codecs or a failed SDP negotiation.

This matters because the fix differs. A provider 488 means changing what you offer. A local 488 means Asterisk could not build an answer from what the caller offered versus what the endpoint allows, so you change the endpoint or add transcoding.

How do I capture the INVITE and the 488?

Turn on SIP message logging and watch one failing call. Do this on a quiet system, because logger output is verbose and SDP can reveal internal addresses.

asterisk -rvvv
pjsip set logger on
pjsip set history on
core set verbose 5
core set debug 3

# independent capture, run from the shell
tcpdump -i any -s 0 -w /tmp/488.pcap port 5060

# or interactive ladder view with SDP
sngrep -d any port 5060
Tip: If the trunk uses TLS (port 5061) the SDP is encrypted on the wire, so tcpdump shows nothing useful. Use pjsip set logger on instead, which prints the decrypted message.

How do I read the SDP in a SIP INVITE?

Each SDP line is type=value. Only a few lines decide whether a 488 happens. Read the m= line first, then the attributes beneath it.

SDP lineWhat to checkPoints to
m=audio 12000 RTP/AVP 0 8 101Profile and payload listRTP/AVP is plain RTP; the numbers are the codecs offered, in preference order
m=audio 12000 RTP/SAVP ...SAVP profileSRTP offered; far side may only accept RTP/AVP
a=rtpmap:8 PCMA/8000Payload to codec map0 PCMU, 8 PCMA, 9 G722, 18 G729, 101 telephone-event; 96 and above are dynamic (Opus is usually 96-127)
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:...SDES keySRTP via SDES
a=fingerprint / a=setupDTLS keyDTLS-SRTP, normally WebRTC
c=IN IP4 10.0.0.5Media addressPrivate IP behind NAT, or 0.0.0.0, or missing
a=sendrecv / a=inactiveDirectioninactive on a first INVITE is unusual and may be refused
a=ptime:20PacketizationOdd values (such as 10 or 60) can be rejected
m=video ... / m=image ... udptlExtra streamsVideo or T.38 where only audio is accepted

Worked example: codec mismatch and its fix

Here Asterisk offers only G.722 and telephone-event. The trunk supports only G.711, so it rejects the call:

--> INVITE sip:15551234567@sip.carrier.example SIP/2.0
m=audio 12844 RTP/AVP 9 101
a=rtpmap:9 G722/8000
a=rtpmap:101 telephone-event/8000
c=IN IP4 203.0.113.10

<-- SIP/2.0 488 Not Acceptable Here
Warning: 305 sip.carrier.example "Incompatible media format"

# after the fix (offer 0 8 101), the answer is:
<-- SIP/2.0 200 OK
m=audio 30112 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
c=IN IP4 198.51.100.20

Codec and SRTP mismatches: how to fix them

For codecs, the offer must contain at least one payload the trunk supports. Set it explicitly on the trunk endpoint. G.729 only works if you have a licensed codec (codec_g729a or a hardware or license solution), and most carriers do not accept Opus, so ulaw and alaw are the safe default.

For encryption, match the m= profile to the provider. If the provider answers 488 to RTP/SAVP, turn SRTP off. If it requires SRTP and you offer RTP/AVP, the rejection comes the other way. SDES (media_encryption=sdes) only protects keys if signaling runs over TLS, since a=crypto keys travel in clear text inside the SDP otherwise.

DTLS-SRTP (media_encryption=dtls) needs additional certificate and verification options on the endpoint, such as dtls_cert_file, dtls_verify and dtls_setup. Check the option names against the pjsip_configuration.txt or sample pjsip.conf shipped with your Asterisk version before using them.

; pjsip.endpoint_custom.conf or the trunk endpoint
[carrier-trunk]
type=endpoint
disallow=all
allow=ulaw,alaw
media_encryption=no        ; or sdes (TLS transport) / dtls
dtmf_mode=rfc4733
direct_media=no
Warning: Changing codecs or encryption on a live trunk affects every call through it. Make the change off-hours, and keep a copy of the existing config. In FreePBX, edit the trunk's Codecs tab and the encryption option in its Advanced tab rather than hand-editing generated files, which are overwritten on reload.

Other SDP problems: NAT addresses, video, T.38 and bridged-leg 488s

If codecs and profile match, check the c= line. A private address such as 10.x in a call to a provider means NAT is not handled, and some carriers reject it. On the PJSIP transport set external_media_address, external_signaling_address and local_net; on the endpoint set rtp_symmetric=yes, force_rport=yes and rewrite_contact=yes. Disable SIP ALG on the router, because it rewrites SDP and can leave a malformed or mismatched c= line.

If the 488 appears when Asterisk bridges two legs, the caller's codecs and the trunk's codecs have no overlap and no translation path exists. Check with core show translation and core show codecs, and confirm the codec modules are loaded with module show like codec. For video m= lines, set disallow=all then allow=ulaw,alaw only (no video codecs) on the trunk. For T.38 rejections, set t38_udptl=no on the endpoint to stop the re-INVITE.

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0
external_media_address=203.0.113.10
external_signaling_address=203.0.113.10
local_net=192.168.0.0/16

Verify the fix and avoid common mistakes

Reload, then place a fresh test call and watch the SIP trace.

Frequent mistakes: allowing codecs on the extension but not on the trunk; leaving SRTP enabled from a template; forgetting to reload; testing with a softphone that offers different codecs than the real phone; and SIP ALG still active.

  1. Reload: pjsip reload for hand edits, or fwconsole reload in FreePBX.
  2. Run pjsip show endpoint carrier-trunk and confirm the allow list and media_encryption value.
  3. Place an outbound test call with pjsip set logger on and confirm the 200 OK SDP lists one codec plus telephone-event.
  4. During the call run core show channels, then core show channel <name> to see the negotiated read and write formats, and pjsip show channelstats to confirm packets in both directions.
  5. Confirm two-way audio and test a DTMF digit.
Tip: If it still fails, ask the provider for their supported codec list, SRTP requirements, and the reason they rejected the INVITE, and give them the Call-ID, timestamp and source IP from your capture.

Common questions

Is a SIP 488 the same as a 606 Not Acceptable?

No. A 488 rejects the request on this particular path, usually because of the SDP, and another route or different offer may work. A 606 is a global failure meaning the user cannot accept the session anywhere.

Why do I get 488 only on outbound calls and not inbound?

Outbound calls make your PBX build the SDP offer, so your codec and encryption settings are judged by the provider. On inbound calls the provider offers and Asterisk answers from its allowed list, which is often more lenient.

Can a 488 be caused by DTMF settings?

Rarely. A telephone-event payload (101) that the far side does not support is usually ignored, but a malformed a=fmtp line for it can be refused. Set dtmf_mode=rfc4733 and keep the payload at 101.

Does enabling transcoding fix a 488 on the trunk?

Only when the two bridged legs lack a common codec. If the trunk itself supports only G.711, Asterisk must offer ulaw or alaw to it and translate from the caller's codec, so the trunk endpoint still has to allow them.

Why does the 488 show in FreePBX even though codecs look right?

Check the endpoint that actually handled the call, with pjsip show endpoint, because FreePBX can apply codecs per trunk and per extension separately. Also check that media_encryption was not inherited as sdes or dtls.

Related topics:sipasteriskfreepbxsdppjsip