| Internet-Draft | CoAP No Content | November 2026 |
| Jiménez & Bormann | Expires 6 May 2027 | [Page] |
This document defines the 2.06 (No Content) response code for the Constrained Application Protocol (CoAP). The code indicates that the target resource exists but has no current representation to transfer. It allows a client to retrieve or observe a resource before that resource has any content, without the server signaling an error. This document updates RFC 7641 to allow 2.06 (No Content) notifications, and specifies how cross-proxies map the code to and from the HTTP 204 (No Content) status code.¶
This note is to be removed before publishing as an RFC.¶
Status information for this document may be found at https://datatracker.ietf.org/doc/draft-jimenez-core-coap-no-content/.¶
Discussion of this document takes place on the core Working Group mailing list (mailto:core@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/core/. Subscribe at https://www.ietf.org/mailman/listinfo/core/.¶
Source for this draft and an issue tracker can be found at https://github.com/jaimejim/draft-jimenez-core-coap-no-content.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 6 May 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
CoAP [RFC7252] defines a set of success response codes in Section 5.9.1 of [RFC7252]. A GET request that succeeds returns 2.05 (Content) with a representation of the target resource. A GET request on a resource that does not exist returns 4.04 (Not Found). CoAP has no code for the case in between: the resource exists, but no representation of it is available yet, or the last representation has been removed or has expired.¶
This case occurs in several CoRE applications. In the publish-subscribe architecture of [I-D.ietf-core-coap-pubsub], a topic-data resource has no content between topic creation and the first publication. Because a GET or Observe registration on such a resource cannot succeed, that specification introduces a "half created" topic state, answers requests in that state with 4.04 (Not Found), and provides an "initialize" property so that a creator can install placeholder data. A client then has to infer the topic state from which operations fail. A sensor whose last reading has expired, or a resource whose value has been cleared, have the same gap.¶
Servers fill the gap today in one of three ways, each with a drawback. A 4.04 (Not Found) response terminates an Observe registration (Section 4.2 of [RFC7641]), so a subscriber cannot register interest until data exists and has to poll instead. A 2.05 (Content) response with an empty payload is ambiguous: a zero-length payload is a valid representation in some Content-Formats (for instance, an empty text/plain string), so the client cannot tell "the value is empty" from "there is no value". A 5.03 (Service Unavailable) response signals a server-side failure when no failure has occurred.¶
HTTP addresses this case with 204 (No Content) (Section 15.3.5 of [RFC9110]): the server has fulfilled the request and there is no content to send. The HTTP-to-CoAP mapping in [RFC8075] maps HTTP 204 only to 2.02 (Deleted) and 2.04 (Changed), which are not used in response to GET.¶
This document defines 2.06 (No Content) for CoAP, specifies its use with GET, FETCH, and Observe, and gives the mapping to and from HTTP 204 (No Content). It does not change the semantics of any existing response code, and it does not define how a resource comes to have no representation; that is up to the application.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP14] (RFC2119) (RFC8174) when, and only when, they appear in all capitals, as shown here.¶
This document uses the terms "resource", "representation", "origin server", "proxy", and "cross-proxy" as defined in [RFC7252], and "observer", "registration", and "notification" as defined in [RFC7641].¶
The 2.06 (No Content) response code indicates that the server has fulfilled the request, that the target resource exists, and that the resource has no current representation to transfer in the response.¶
A server MUST NOT include a payload in a 2.06 (No Content) response. A server MUST NOT include a Content-Format Option or an ETag Option in a 2.06 (No Content) response, since there is no representation to describe or tag.¶
A client that receives 2.06 (No Content) learns that the resource exists. If the client holds a representation of the resource from an earlier response, it MUST NOT treat that representation as the current state of the resource.¶
A server uses 2.06 (No Content) in response to GET and FETCH [RFC8132] requests. For FETCH, the code indicates that the target resource exists and the selected part of it has no representation.¶
A server MUST NOT use 2.06 (No Content) in response to PUT, POST, PATCH, iPATCH, or DELETE requests. Those methods already have success codes that carry no payload: 2.04 (Changed) and 2.02 (Deleted).¶
A 2.05 (Content) response with a zero-length payload carries a representation of length zero in the indicated Content-Format. A 2.06 (No Content) response carries no representation at all. A server that has an empty representation of a resource, such as the empty CBOR array or an empty string, returns it with 2.05 (Content). A server that has no representation returns 2.06 (No Content).¶
A 4.04 (Not Found) response indicates that the server has no resource at the target URI. A server MUST NOT return 2.06 (No Content) for a URI at which no resource exists.¶
A 2.06 (No Content) response is cacheable. Caches use the Max-Age Option to determine freshness (Section 5.6.1 of [RFC7252]). A server SHOULD set Max-Age to the time after which it expects the resource may have a representation, if known. A cached 2.06 (No Content) response satisfies subsequent GET requests with the same cache key while it is fresh.¶
A client MAY include ETag Options in a GET request on a resource that currently has no representation. Since none of the entity tags can match, the server responds with 2.06 (No Content).¶
An endpoint that does not implement this document handles 2.06 (No Content) by the rule of Section 5.2 of [RFC7252] for an unrecognized Success class code: the request succeeded, without further details. Since a 2.06 response carries neither a payload nor a Content-Format Option, such a client observes what it observes on a 2.05 (Content) response with an empty payload and no Content-Format Option, which is one of the responses listed in Section 1. Receiving 2.06 therefore gives such a client the same information as the response it receives from a server that does not implement this document.¶
A cache that does not implement this document does not store a 2.06 response, as Section 5.6 of [RFC7252] requires for unrecognized Success class codes. A cache that does implement it stores the response per Section 3.4.¶
An observer that does not implement this document remains registered on a 2.06 notification, since Section 4.2 of [RFC7641] removes observers only on non-2.xx notifications, and treats the notification as an empty representation, as it would a 2.05 (Content) notification with an empty payload.¶
For these reasons, a server that implements this document sends 2.06 (No Content) whenever Section 3.1 applies, without regard to what it knows about the client. A server has no signal of the capabilities of the client, and when a proxy is in the path it does not see the client at all. Each alternative response (Section 1) is worse for clients that implement this document and no better for clients that do not.¶
Observe [RFC7641] is one consumer of 2.06 (No Content); the code itself is defined by Section 3 independently of it. The following subsections specify how registrations and notifications use the code.¶
A client registers interest in a resource that has no current representation by sending a GET request with an Observe Option set to 0. A server that supports this document and is willing to add the client to the list of observers responds with 2.06 (No Content) and includes an Observe Option. As with any 2.xx response that carries an Observe Option (Section 3.1 of [RFC7641]), this confirms the registration.¶
Section 4.2 of [RFC7641] states that a notification SHOULD have a 2.05 (Content) or 2.03 (Valid) response code. This document adds 2.06 (No Content) to that list.¶
When the resource of an observed registration gains a representation, the server sends a 2.05 (Content) notification as usual. When the resource loses its representation, for instance because the data was removed or has expired, the server sends a 2.06 (No Content) notification that includes an Observe Option. The client remains on the list of observers. On receipt, the client discards the previously notified representation, per Section 3.1.¶
A 2.06 (No Content) notification follows the ordering rules of Section 3.4 of [RFC7641] and the freshness rules of Section 3.2 of [RFC7641], using its Observe sequence number and Max-Age Option.¶
Section 4.2 of [RFC7641] requires the Content-Format of a 2.xx notification to be the same as the one used in the initial response. This requirement does not apply to 2.06 (No Content) notifications, which carry no Content-Format Option.¶
If the initial response to a registration is 2.06 (No Content), the Content-Format of the first 2.05 (Content) notification determines the Content-Format for all subsequent 2.05 (Content) notifications of that registration. A client that needs a specific Content-Format SHOULD include an Accept Option in the registration request, so that the server can reject the registration with 4.06 (Not Acceptable) if it cannot produce that format.¶
2.06 (No Content) is an end-to-end response code. A CoAP-to-CoAP proxy forwards it unchanged and caches it per Section 3.4.¶
A proxy that does not implement this document forwards a 2.06 (No Content) response like any other response and does not cache it (Section 5.6 of [RFC7252]). A proxy that implements this document does not translate 2.06 for clients that might not recognize it: the response code is end-to-end, and the proxy has no better knowledge of the client than the origin server has (Section 3.5).¶
[RFC8075] defines no mapping for CoAP response codes absent from Table 2, so the behavior of an HTTP-to-CoAP cross-proxy that does not implement this document is implementation-specific. A CoAP-to-HTTP cross-proxy that does not implement this document maps HTTP 204 (No Content) in response to GET to 2.05 (Content) with an empty payload, per Section 10.1.1 of [RFC7252].¶
An HTTP-to-CoAP cross-proxy that implements this document maps a CoAP 2.06 (No Content) response to an HTTP 204 (No Content) response, as if Table 2 in Section 7 of [RFC8075] contained that row. The proxy translates Max-Age into HTTP freshness information as specified in [RFC8075].¶
A CoAP-to-HTTP cross-proxy that implements this document (Section 10.1 of [RFC7252]) maps an HTTP 204 (No Content) response to a GET request into a CoAP 2.06 (No Content) response. For other methods, the existing mappings to 2.04 (Changed) and 2.02 (Deleted) apply.¶
This section is informative. Messages are written in the CoAP Diagnostic Message Notation [I-D.jimenez-core-coap-diag]. The section shows how a publish-subscribe broker following [I-D.ietf-core-coap-pubsub] could use 2.06 (No Content), assuming the broker creates the topic-data resource together with the topic.¶
A subscriber reads the topic-data resource before any data has been published, then registers for notifications. Both requests succeed:¶
GET /ps/data/1bd0d6d 2.06 No Content Max-Age: 600
GET /ps/data/1bd0d6d Observe: 0 Accept: 110 (application/senml+json) 2.06 No Content Observe: 1 Max-Age: 600
A publisher then publishes the first value. Since the resource already exists, the broker returns 2.04 (Changed), and notifies the subscriber:¶
PUT /ps/data/1bd0d6d
Content-Format: 110 (application/senml+json)
[{"bn":"urn:dev:os:32473-123456","n":"temperature","u":"Cel","v":23}]
2.04 Changed
2.05 Content
Observe: 2
Content-Format: 110 (application/senml+json)
Max-Age: 15
[{"bn":"urn:dev:os:32473-123456","n":"temperature","u":"Cel","v":23}]
If the data later expires, the broker sends a 2.06 (No Content) notification. The subscriber stays registered and stops using the value of 23 Cel:¶
2.06 No Content Observe: 3 Max-Age: 600
With this code, the broker needs neither a separate "half created" state nor 4.04 (Not Found) responses on an existing topic, and subscribers can register at any time after the topic is created.¶
The security considerations of [RFC7252] and [RFC7641] apply.¶
A 2.06 (No Content) response tells the client that a resource exists at the target URI, which a 4.04 (Not Found) response would not. A server that does not want to disclose the existence of a resource to an unauthorized client MUST respond with the same code it uses for nonexistent resources, as it would for any other request from that client.¶
A 2.06 (No Content) response carries no payload and is smaller than the request that triggered it, so it does not add an amplification vector. Observe registrations accepted on resources with no representation keep observer state on the server for longer than registrations that would otherwise fail with 4.04 (Not Found). Servers apply the same limits on the number of observers that they apply to any other resource (Section 7 of [RFC7641]).¶
IANA is asked to add the following entry to the "CoAP Response Codes" registry within the "Constrained RESTful Environments (CoRE) Parameters" registry group, defined in Section 12.1.2 of [RFC7252]:¶
| Code | Description | Reference |
|---|---|---|
| 2.06 | No Content | [RFC-XXXX] |
The code 2.06 is a suggested value; it is unassigned in the registry, and the registration policy is IETF Review or IESG Approval.¶
Note to RFC Editor: replace [RFC-XXXX] with this document's number.¶
This appendix records the alternatives considered. It is to be removed before publication.¶
Requires no new code, but cannot distinguish an empty representation from an absent one, and constrains the Content-Format of an Observe registration before any data exists.¶
Conflates "no resource" with "no content", and terminates Observe registrations, so subscribers have to poll until data appears.¶
Signals a temporary server failure; caches and clients treat it as an error, and it also terminates Observe registrations.¶
An application-defined "empty" value, as with the "initialize" property of [I-D.ietf-core-coap-pubsub]. Media types that have an empty, null, or undefined value can express the absence of content within the type. The meaning of that value is specific to each media type, existing media types cannot be retrofitted with one, and a generic client cannot recognize it.¶
A dedicated Content-Format that denotes the absence of content, sent in place of the requested representation. A response in this format conflicts with an Accept Option in the request. Introducing it would require changing the semantics of Accept to permit this format in any response or notification.¶
An application/multipart-core container [RFC8710] that holds either a marker for the absence of content or the intended representation, so that one Content-Format covers both states. The outer format is fixed, so the client can no longer select the representation format with the Accept Option.¶
Used for this purpose in early revisions of [I-D.ietf-core-coap-pubsub]. 2.04 (Changed) is defined for the result of PUT and POST, and reusing it for GET overloads its meaning.¶
Would follow the pattern by which 2.03 (Valid) and 2.31 (Continue) are only sent to clients that asked for them. Costs an option number and a byte per request to protect clients that already treat an unrecognized 2.xx as success (Section 5.2 of [RFC7252]), and the fallback for requests without the option is the empty 2.05 (Content) response those clients receive without this document.¶
Mike Bishop suggested a No Content success code during the AD review of [I-D.ietf-core-coap-pubsub]. Michael Koster proposed a dedicated 2.06 code in issue 4 of the [I-D.ietf-core-coap-pubsub] repository, including the requirement that a client stop using a stale value.¶