CoAP Separate Responses: Do Not Treat an Empty ACK as the Completed Operation

After a CoAP empty ACK, stop waiting for acknowledgement of the request message but keep waiting for its response. Do not display a successful operation, release its result owner, or assume that a physical action finished merely because the request was acknowledged.

This article covers unicast confirmable requests over UDP under RFC 7252, especially the interval after an empty acknowledgement. It does not tune the retransmission schedule for an unacknowledged request. The proposed state machine must be adapted to the actual library’s callbacks and cancellation API; no stack or target execution is claimed.

1. Give acknowledgement and result separate states

RFC 7252 section 5.2.2 allows a server to acknowledge a request before sending a separate response. The later response has its own message exchange and is associated with the request by its Token. An empty message contains no response code or payload. The separate-response model therefore requires a client state that means “acknowledged, result pending.”

Client state What is known What is still unknown
Request sent The local stack submitted the request. Whether the server received or acted on it.
Empty ACK received The request message was acknowledged. The response outcome and any product-specific completion.
Response validated A response belongs to the request and has a valid representation. Anything the resource contract does not promise.
Local wait ended The caller no longer waits for a result. Whether server-side work has stopped or completed.

These are suggested application states. Map them to the library’s existing exchange state rather than creating a competing retransmission engine above it. A callback named “sent” or “acknowledged” needs documented semantics before the interface treats it as completion.

Client state graph keeps empty acknowledgement separate from response completion and from an unresolved local timeout or cancellation.
The response-wait budget is an application policy. Message acknowledgement does not establish a physical operation’s completed result.

2. Define a response-wait deadline

RFC 7252 notes that an application may need a timeout unrelated to CoAP retransmission timers if a server never sends its separate response. That observation does not prescribe a universal response-wait value. See section 5.2.2.

Choose the deadline from the resource operation and user requirement. State whether it is measured from initial submission or from acknowledgement. A total-operation deadline is often easier for a caller to understand; a post-ACK budget can also be valid if the resulting total limit is explicit. Use a monotonic clock and preserve the original deadline when duplicate acknowledgements arrive.

Bound the number of pending acknowledged requests and their retained memory. A server that acknowledges promptly but never responds can exhaust a client just as effectively as a silent peer. When capacity is exhausted, reject or defer new work under a defined policy rather than allocating another unbounded pending entry.

3. Accept valid event orderings

A separate response can arrive before the request’s empty ACK because UDP delivery can reorder them. It may also be confirmable or non-confirmable. RFC 7252 requires clients to handle the permitted forms; the response transmission rules cover those cases.

The response path must therefore be able to finish a request that is still locally marked “awaiting ACK.” A later ACK must not reopen the request, produce another callback, or cancel the already accepted result. If the response is confirmable, let the stack perform its message acknowledgement even when application processing is dispatched elsewhere.

Likewise, a duplicate confirmable response must not make the application apply the result twice. Separate message-layer handling from the single application completion transition. Do not discard all exchange state merely because the user-facing callback has run if the stack still needs its documented duplicate-handling state.

4. Make cancellation local unless the resource says otherwise

A local cancellation can release the caller’s interest. It does not retract a request already delivered to the server. Define whether a late response is logged, used for reconciliation, or ignored by the application while the protocol stack handles it appropriately.

If the resource represents a consequential operation, retain enough nonsecret application identity to query its status through a documented mechanism. Do not automatically submit the same action again after the response-wait deadline unless the resource’s idempotency and retry contract permits it. A second CoAP request may be a second action.

Remote cancellation, when required, needs an application resource or operation defined for that purpose. Sending a Reset for an unexpected message is not a general protocol for undoing physical work. Keep these meanings separate in logs and user-facing states.

5. Qualify a deterministic event script

Script Acceptance condition
Empty ACK, then a successful response before the deadline. The caller remains pending after ACK and completes once after response validation.
Empty ACK, then an error response. The caller receives the actual failure result; the ACK never created a false success.
Empty ACK, then silence. The response-wait deadline produces an explicit unresolved outcome and bounded cleanup.
Response first, delayed ACK second. The valid response completes once; the delayed ACK does not alter the terminal result.
Cancel while acknowledged; deliver a late response. No callback reaches a released owner or a newly allocated request.
Lose the response’s ACK and repeat the response. Protocol handling continues correctly without a second application result.

Run the deadline/response race in both orders. Record the winning terminal transition, stack event, Token association, and callback count. Timer cancellation alone is insufficient if a timer callback is already queued.

Hypothetical interface correction

A maintenance panel requests a device self-test and changes its label to “passed” when an empty ACK arrives. The device later returns a failure response, but the panel has already released the request. The corrected interface shows “request acknowledged, test result pending,” then interprets the eventual response under the resource contract.

The same correction applies even if the eventual result is merely a job identifier rather than completion of the test. Protocol response success and the meaning of that response must both be checked.

Finally, retain the applicable secure Token-binding rules from RFC 9175 section 4.2 when recycling client request state. Release evidence should include the state map, response deadline, cancellation semantics, and event scripts. An empty ACK closes one uncertainty, not every uncertainty about the operation.

Similar Posts