Respond to unknown PUBREL with PUBCOMP reason code 0x92#379
Open
guclumhg wants to merge 1 commit into
Open
Conversation
A client that loses its QoS 2 session state (e.g. the device reboots after sending PUBREC) receives a retransmitted PUBREL on reconnect. Since no publish record exists for the packet identifier, the state update fails, no response is sent, and MQTT_ProcessLoop returns MQTTBadResponse forever, leaving the client unusable. MQTT v5 requires a PUBCOMP response to every PUBREL [MQTT-4.3.3-11] and defines reason code 0x92 (Packet Identifier not found) for this situation, noting it is not an error during recovery. Send that response instead of failing, without creating a state record. Fixes FreeRTOS#271
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
When a client loses its QoS 2 session state (for example the device reboots after sending a PUBREC) and reconnects with a persistent session, the broker retransmits the pending PUBREL. Because
incomingPublishRecordsno longer contains the packet identifier,MQTT_UpdateStateAckfails, no response is sent, and every subsequentMQTT_ProcessLoopcall returnsMQTTBadResponse— the client is permanently stuck, as reported in #271.MQTT v5 defines the recovery for exactly this situation: the receiver of a PUBREL must respond with a PUBCOMP [MQTT-4.3.3-11], and reason code 0x92 (Packet Identifier not found) exists to signal that the identifier was not known — the specification notes this "is not an error during recovery". The enum value
MQTT_REASON_PUBCOMP_PACKET_IDENTIFIER_NOT_FOUNDalready exists in coreMQTT but was never sent on this path.This PR makes
handlePublishAcksdetect the record-not-found case for an incoming PUBREL (MQTT_UpdateStateAckreturnsMQTTBadResponsefor a PUBREL only when no record exists; a known record with an illegal transition yieldsMQTTIllegalState) and respond with a PUBCOMP carrying reason code 0x92 and no properties, reusing the existingMQTT_GetAckPacketSizeandbuildAndSendAckWithPropshelpers. The process loop then returns successfully and the connection stays usable. The message is lost, which the issue reporter considered acceptable for this corner case. No state record is created for the response, the application callback is not invoked, and the retransmit hooks are not touched. Behavior for every other packet type and failure is unchanged — an unknown PUBACK/PUBREC/PUBCOMP still fails as before, covered by a regression scenario in the new test.Scope note: on the outgoing side, publish persistence across reboots is now possible through the store/retrieve/clear retransmit hooks, so this PR focuses on the incoming PUBREL failure that rendered the client unusable. The symmetric case (unknown PUBREC answered with PUBREL 0x92) can be added as a follow-up if desired.
Coverage: all 16 new lines and all 18 new branches are covered by the added test (5 scenarios); totals remain at 97.5% lines / 93.8% branches.
Test Steps
Both CI unit-test configurations pass locally (5/5 test suites), including the new
test_MQTT_ProcessLoop_UnknownPubrel_RespondsWithPubcompNotFound:Formatting verified with uncrustify 0.69.0 using the config from FreeRTOS/CI-CD-Github-Actions.
Checklist:
Related Issue
Fixes #271
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.