Change:
in inner-options. The Outer Max-Age option is used to avoid unnecessary caching of <del> OSCORE responses at OSCORE unaware intermediary nodes.  A server MAY set a Class U Max-Age option with value zero to Observe responses (see Section 5.6.1 of RFC7252) which is then processed according to outer-options.  The Outer Max-Age option value SHALL be discarded by the OSCORE client. </del> <ins> OSCORE error responses at OSCORE unaware intermediary nodes.  A server MAY set a Class U Max-Age option with value zero to OSCORE error responses described in replay-protection, ver-req and ver-res, which is then processed according to outer-options. </ins> <del> Non-Observe OSCORE responses do not need to include a Max-Age option </del> <ins> Non-error OSCORE responses do not need to include a Max-Age option </ins> since the responses are non-cacheable by construction (see coap- header).

Discussion:
on server side. Also, error is unprotected (as all other OSCORE errors) see
RFC7252 specifies that 5.03 uses Max-Age. Now when we use 4.01, I think Max-Age should (need to) be removed.
NAME This was an oversight on my part. One question though: what was the reason to say: Why do we specify for Observe responses? A server MAY set an outer Max-Age=0 with all responses (as an indication to the proxy not to cache), also for error responses (not protected with Object-Security) to an OSCORE request.
The reason why we talked about Max-Age is to avoid caching by a OSCORE unanaware proxy. This was not needed for 2.04. if we change to only 2.04 we should remove this completely.
Ok, because 2.04 is non cacheable. but error responses are cacheable, so following the same logic we should say that the server MAY set max-age = 0 for error responses, no?
Yes, that makes sense.
(This issue takes some context from issue ). The current draft states that replay protection violation triggers a 5.03 with Max-Age 0 (Section 6.4). While this is a practical solution to issue (which is not mitigated by encrypting the code because FETCH is still safe), it could still be caught by a proxy that'd try to be smart about it (and would, AFAICT, be within its rights). I suggest that the response code be 4.01 Unauthorized with Max-Age=0. The semantics of Unauthorized are "SHOULD NOT repeat the request without first improving its authentication status to the server", and while it's a bit of a stretch to say that increasing the sequence number is sufficient to improve the authentication status, the Max-Age gives a good hint ("Come on, try again right away, don't look for other keys"), and clients can use the presence of the Max-Age option as a discriminator to tell "Sorry, no such context" apart from "Retry with a new seqno".
We also just identified this response code as not appropriate. The proposal is good, unless it results in overloading the semantics of Max-Age=0.

There is already at least one requirement when Max-Age has to be zero: RFC7252, Section 5.6.1: "If an origin server wishes to prevent caching, it MUST explicitly include a Max-Age Option with a value of zero seconds." Is there a setting where the the server would not want the response 4.01 to be cached even though it is not a replay? (Obviously we have to differentiate between Inner and Outer 4.01, but is that enough?)
I don't know. I briefly thought about using an Echo here, but an HTTP proxy would react to that as a CoAP proxy would to 5.03,Max-Age=0. (See comments 2ff). I did give that some thought, and considering the Echo option thought about whether the server should just reply with an encrypted ,Max-Age=0 (or Echo=short). I decided against suggesting that because responding to a possibly fraudulent message with an owned partial IV means that any adversary that has one valid-but-used message can thus drive any server into partial-IV exhaustion.
By the way, just FYI, that Max-Age=0 with 5.03 means "service unavailable, retry in 0 seconds", which is wrong (and not what we want). (see: URL)
The current text where there MAY be a Max-Age of 0 both on "4.01, Security context not found" and on "4.01, Security context not found" means that a client can not know any more which is the case (and it should not look into the message). I see the reason for the MAY set Max-Age for most error cases in , but a client needs to keep those apart (otherwise it'd need to so something like try 3 times with a new PIV, and if the server still responds the same, assume that it doesn't know the KID). I suggest that for those two responses, the Max-Age values are enforced as "MUST NOT set a Max-Age option" and "MUST set the Max-Age option to 0", or find any other discriminator, but an implementation should be able to tell them apart.

Granted, with the current setup of POST and FETCH there are much fewer cases where replay protection errors can happen (they'd only legally happen under particular package loss situations when starting an observation via a proxy that does not support observation but does do optimizations for safe requests), but I still think that there'd be more clarity if there were a discriminant between the two error cases.