Asterisk 16 PJSIP invalid value error exception when parsing 'Contact' header

I’m using Asterisk 16 on OpenBSD 6.7
by incoming calls I’m getting this PJSIP error, which seem to be annoyed by the “expires=” value in the “contact” header.
I’m not sure how I could solve this! To my understanding, this value was set by my ISP.
any thoughts ?

[May 21 13:58:33] ERROR[504612]: pjproject: <?>:               sip_transport.c Error processing 950 bytes packet from UDP : PJSIP invalid value error exception when parsing 'Contact' header on line 3 col -1:
INVITE;transport=udp SIP/2.0
Contact: <>;expires=4294967295
Content-Type: application/sdp
CSeq: 276069520 INVITE
From: "XXXXXXXX" <;user=phone>;tag=12529-YY-10f20f6e-723df48f0
Max-Forwards: 28
Record-Route: <;lr>;session=343167
To: <;user=phone>
Via: SIP/2.0/UDP;branch=z9hG4bK-ECBQ-6a2c050d-545126f1
P-Preferred-Identity: <;user=phone>
User-Agent: wtnet/ngn (2)
Content-Length: 249


There’s nothing you can do directly. Looking at the RFC this is valid, and the highest number possible. The PJSIP validation is probably too aggressive. You can file an issue[1] in Asterisk, but I have no time frame on when it will get resolved.


While it is technically valid, the parameter is meaningless, because expires is only actually used on 302 responses and on registrations.

Thanks for the info, can you think of any workaround ?

Thanks for the clarification. I will file the issue.

Where is the user portion of the Contact Header? There should be a user portion for the contact header on INVITEs. It can’t parse the header because pieces it expects to parse are missing.

The formal syntax requires a SIP-URI (or SIPS-URI, or absolute URI). SIP-URIs don’t require a user part, and I can’t find anything in the narrative that overrides this for INVITEs.

Could you please identify the part of the RFC that requires a user part.

Yes, the user portion of SIP URI is optional and may not be used when the destination has no concept of users or the the host portion is being used to identify. However, the Contact Header is used to tell the other side when the requester expects requests/replies to be sent during the transaction.This would mean INVITEs, REGISTERs to name a few.

This is why Chan_SIP sets the user to s when you use a register string without a /extension portion and why Chan_PJSIP defaults to the user asterisk for the contact user for requests. Because most requests require there to be a full SIP URI for the contact header which includes the user portion.

This isn’t the Contact being sent by Asterisk. Any user part of the Contact header should only be interpreted (as part of the resulting request URI) by the system that sent the Contact header. Asterisk should accept any syntactically well formed URI for schemes that it supports.

Please show me where your providers DO NOT send a user portion in the Contact Header when sending an INVITE to you.

See this is a parsing error, since the Contact Header is in a correct format per RFC (user not there and not required) but you see this is an INVITE which means the Contact Header contains the actual contact that made the request and where your replies should ultimately end up for that INVITE request. The Record-Routes will show you HOW it got there and the path to use for replies and new requests in the transaction but ultimately the Contact Header holds the real requester.

So now Asterisk is trying to parse this header and expects X values to be returned by that parse and if a value is missing, like the user portion of the header, then the parse is incomplete and missing pieces that should be there after the parse.

That is my theory on this. Yes, as it stands the Contact Header is formatted correctly per the RFC because the user isn’t always required (sometimes it is just not always) which means that Asterisk must expect more data in the header (like a user) to complete the parse for the INVITE.

Record-Route only applies to the current request. Contact is the address to be used for subsequent requests in the session.

One reason that they can differ is because of proxies maintaining state, in which case they need to stay in the recorded route until the response is passed back. The only purpose of Contact in an INVITE request is to provide a direct address back that can be used independently of the recorded route.

One reason for maintaining state on a request is that the proxy is sending the 100 responses, so needs to know when there has been a response and it no longer needs to send them.

From questions we have seen in the past, there are some ITSPs that try to read more into Contact than the correct place to which to send subsequent transactions. Typically they expect the Contact header to contain the remote party address. However they are wrong in using it for that purpose.

OK, we can debate this all day really. However, the key issue here is the contact header can’t be parsed by Asterisk. So again, if you go to parse something and expect 8 values to be returned once parsed and only get 7 then what you are parsing is incorrect. Same if you end up with 9 instead of 8, something isn’t right.

So I’m not disagreeing that the contact header is a right format because, as said before, the user portion isn’t mandatory for all requests but only requests where the user portion would be required/needed for what is happening. Is this one of them?