Find your error
You do not need to read this guide from start to finish. Match your client library or MQTT version, then jump to the code. 135 and 0x87 are the same value; PubSubClient -4 and MQTT 3.1.1 CONNACK 4 are not.
- ESP32 / ESP8266 with PubSubClient: rc=-2: connection failed ; rc=-4: timeout .
- Authentication or permission denied: 134 / 0x86: bad credentials ; 135 / 0x87: not authorized .
- Repeated disconnections: 141 / 0x8D: Keep Alive timeout ; 142 / 0x8E: session taken over .
- Paho errors: Python 7 ; Java 32109 / EOFException .
- Network or certificate failures: ECONNREFUSED, TLS, WebSocket 1006 .
If you know the value, use your browser’s find-in-page search. For other values, use the contents to reach MQTT 5 , MQTT 3.1.1 , or client-library errors . The 77 entries include all 43 assigned MQTT 5 values, but are not an exhaustive catalogue of every SDK error.
Identify the failed operation
A failed publish or subscription acknowledgement does not by itself mean the connection closed. The same number can also have a different meaning in another packet or protocol version. MQTT 5.0 · MQTT 3.1.1
MQTT 5 reason codes
Choose the symptom group, then find the value. Each entry lists its applicable packets: a failed SUBACK or PUBACK does not by itself close the connection. This section covers 35 failure codes and 8 success or progress codes. MQTT 5.0 standard
- Identity and permissions
- Server availability and redirection
- Keep Alive, sessions, and disconnection
- Topics, subscriptions, and supported features
- Inflight messages, size, and quotas
- Packet format and other errors
Identity and permissions
132 (0x84): Unsupported Protocol Version
Packets: CONNACK
The endpoint does not accept the requested MQTT version. For example, the client requests 5.0 from an endpoint configured for 3.1.1 only.
- Edit the client’s MQTT version, choose a supported version, reconnect, and inspect CONNACK in Trace.
- Changing a TCP port alone does not change the MQTT version.
Choose the MQTT version supported by your broker in Edit Client. This is a settings example, not a reproduction of CONNACK 0x84.
133 (0x85): Client Identifier not valid
Packets: CONNACK
The broker rejects the Client ID, for example because of its format or length. This is different from 0x8E, where a duplicate ID replaces an existing connection.
- Edit Client ID to an accepted identifier and verify successful CONNACK in Trace.
- A platform that binds identities to registered devices requires an authorized ID, not an arbitrary replacement.
The encoded Client ID is longer than this broker’s configured maximum 24. CONNACK 0x85 identifies a Client ID rejection.
The actual CONNECT preserves the complete syntactically legal Client ID (40 UTF-8 bytes). It exceeds this broker’s configured 24-byte ID policy and receives CONNACK 0x85; this is not a duplicate-ID takeover.
134 (0x86): Bad User Name or Password
Packets: CONNACK
Connection authentication failed. Saved credentials may be stale, or the username and password fields may not match the platform’s required format.
- Edit the client’s authentication details, enter valid credentials, and inspect CONNACK in Trace.
- Verify input and credential validity; disabling certificate verification does not fix an MQTT username or password rejection.
EMQX rejects the deliberately incorrect test password with CONNACK 0x86. The screenshot does not expose the password.
Edit credentials in the native client form while keeping the password masked. This is an unsaved settings illustration, not a new 0x86 response or proof that corrected credentials were accepted; the real rejection is shown separately.
135 (0x87): Not authorized
Packets: CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
The current operation is not authorized. A client may connect successfully but lack permission to publish to factory/cmd. A failed PUBACK is not itself a DISCONNECT.
- Identify the rejected operation in Trace and record its topic and identity.
- Have the administrator check permission for that operation, then retry the same identity and topic rather than merely changing the password.
The publish is rejected with PUBACK 0x87. This same captured connection subsequently exchanges PINGREQ/PINGRESP, so the failed acknowledgement is not itself a disconnect.
138 (0x8A): Banned
Packets: CONNACK
The server has banned the client. This is not an ordinary password typo, and repeated reconnect attempts will not lift the ban.
- Save the rejection from Trace and give the administrator the Client ID, account, and timestamp to check ban records.
- Retry after the restriction is resolved; do not rotate identities to evade it.
The broker has explicitly banned this dedicated test Client ID. Its rejection is CONNACK 0x8A, not an ordinary wrong-password result.
140 (0x8C): Bad authentication method
Packets: CONNACK, DISCONNECT
The authentication method is unsupported or inconsistent with the exchange. This differs from 0x86, which rejects credentials rather than the method itself.
- Edit the client’s Authentication Method to match the broker configuration.
- Inspect CONNECT, AUTH, and CONNACK in Trace; both the method name and its exchange must agree.
Server availability and redirection
Mosquitto rejects the unsupported authentication method with CONNACK 0x8C.
The actual CONNECT requests SCRAM-SHA-256. This Mosquitto endpoint does not implement that enhanced method and returns CONNACK 0x8C. The failure is a method mismatch, not evidence of an incorrect password.
Choose an authentication method that the broker actually implements. Mqttable exposes SCRAM-SHA-256 here; this unsaved settings example does not prove the method is supported by the shown endpoint or that authentication succeeded.
136 (0x88): Server unavailable
Packets: CONNACK
The server answered the MQTT connection request but cannot currently provide service. Receiving CONNACK distinguishes this from a TCP connection that never succeeded.
- Confirm the intended environment and check broker health.
- Retry the same connection settings after service recovery.
137 (0x89): Server busy
Packets: CONNACK, DISCONNECT
The broker cannot currently continue processing this client’s requests. It can reject a connection or close an established one; the code does not identify the exact bottleneck.
- Stop bulk tests or rapid publishing and reduce concurrent clients. Ask the administrator to check broker resources and logs.
- After recovery, verify one client before gradually increasing load.
139 (0x8B): Server shutting down
Packets: DISCONNECT
The server is shutting down and closing established connections. Check for maintenance, a restart, or a node being taken out of service.
- Check the broker’s maintenance, restart, or node-removal records.
- Wait for recovery or use an administrator-provided available endpoint, then verify connection and subscriptions. Do not reset credentials or Client ID for this code.
156 (0x9C): Use another server
Packets: CONNACK, DISCONNECT
The server requests a temporary switch to another server, not a permanent migration. An optional Server Reference may supply the destination.
- Inspect Server Reference in Trace and confirm the destination with the administrator.
- Create or select that broker endpoint in Connections, retaining the original address. Verify TLS and authentication; do not assume automatic redirection.
Native EMQX evacuation sends DISCONNECT 0x9C and Server Reference 127.0.0.1:21883, an owned Mosquitto test listener. This is a temporary server suggestion, not proof that Mqttable automatically redirects.
The native client receives CONNACK 0x9C with Server Reference 127.0.0.1:21883. The reference is a temporary server suggestion; the following target selection and connection are explicit manual operations, not proof of automatic redirection.
Manually select the saved target broker whose endpoint matches Server Reference 127.0.0.1:21883. This controlled lab uses plain MQTT on loopback; it is a manual profile switch, not automatic redirection or proof of old-session continuity.
After the explicit manual switch, this separate MQTT 5 target-probe client connects successfully with CONNACK 0x00. It verifies target reachability, not automatic following of the reference, migration of the original client ID, or restored subscriptions/session state.
157 (0x9D): Server moved
Packets: CONNACK, DISCONNECT
The server requests a permanent change of server location. Unlike temporary switching with 0x9C, the saved configuration should be updated.
- Use the Server Reference supplied by the server or obtain the verified destination from the administrator.
- Update the saved server address, port, and required TLS settings, then verify connection, subscriptions, and received messages.
Keep Alive, sessions, and disconnection
141 (0x8D): Keep Alive timeout
Packets: DISCONNECT
The broker received no MQTT control packet from the client within 1.5 times the effective nonzero Keep Alive. A 20-second value gives 30 seconds; business messages are not the only packets that count.
- Check the client’s Keep Alive and any Server Keep Alive in CONNACK.
- Enable Trace → Heartbeat visibility and inspect PINGREQ/PINGRESP. Missing outbound heartbeats warrant checking sleep or blocked execution, not simply setting Keep Alive to zero.
The client sends no further MQTT control packets after connecting with Keep Alive 1 second. EMQX closes it with DISCONNECT 0x8D.
The original CONNECT sets Keep Alive=1s. A real heartbeat succeeds before the relay starts discarding only client-to-broker MQTT traffic; broker-to-client observation remains intact.
The client-side capture retains the last successful PINGRESP and later outgoing PINGREQ packets. The relay drops those later upstream bytes but forwards the broker’s real DISCONNECT 0x8D. This is the original blocked-uplink scenario, not merely a silent client.
142 (0x8E): Session taken over
Packets: DISCONNECT
Another connection used the same Client ID, causing the broker to close the old one. A debugger borrowing a device ID can create repeated takeovers when both reconnect.
- In Connections, change the debugging client’s Client ID to a separate authorized value and stop duplicate instances.
- Verify both distinct IDs stay connected. Toggling Clean Start does not solve concurrent identity collisions.
Two controlled sockets use probe-session-taken. Mosquitto accepts the new connection and sends DISCONNECT 0x8E to the old one. No production device ID or reconnect loop is used.
Use distinct IDs: after the second client connects, both connections complete a real PINGREQ/PINGRESP exchange. Neither is taken over in this control. The clients disconnect normally only after the test; this is captured concurrent-liveness evidence, not a claim that they remain online forever.
152 (0x98): Administrative action
Packets: DISCONNECT
An administrative action closed the connection, such as a manual disconnect or management operation. Either endpoint can send it; do not automatically blame the broker administrator.
- Check DISCONNECT direction and timestamp in Trace, then consult that endpoint’s management logs.
- Reconnect after the action is resolved. A recurring policy issue needs a policy fix, not faster reconnects.
Mosquitto’s shipped dynamic-security plugin disables the connected test account and sends DISCONNECT 0x98. The packet direction and captured operation establish that this is a server-side administrative disconnect.
160 (0xA0): Maximum connect time
Packets: DISCONNECT
The connection reached its authorized maximum lifetime, even if traffic and heartbeats remained healthy. This is neither Keep Alive timeout nor offline session expiry.
- Check the server’s maximum connection-lifetime policy and reconnect as required. Increasing Keep Alive does not change that policy; this code alone does not prove that credentials expired.
Topics, subscriptions, and supported features
143 (0x8F): Topic Filter invalid
Packets: SUBACK, UNSUBACK, DISCONNECT
The Topic Filter was rejected. The standard also uses this for a correctly formed filter that is unacceptable for this client; it is not always a wildcard syntax mistake.
- Inspect the SUBSCRIBE or UNSUBSCRIBE filter in Trace.
- Retry a permitted exact topic instead of a broad filter. Also check
+and#placement; malformed syntax can instead produce0x81or0x82.
This actual response is DISCONNECT 0x8F after the invalid filter lab/#/invalid. Other brokers can reject the same malformed filter with a different code.
The filter lab/temp is syntactically legal. With native max_topic_levels=1, EMQX returns SUBACK 0x8F because it has two levels. This is policy rejection, not malformed wildcard syntax.
The original request asks for lab/temp at QoS 1. The two-level filter reaches the broker and receives SUBACK 0x8F under its one-level policy.
Correction: use the legal one-level filter lab. Without changing the broker policy, the request receives SUBACK 0x01 (granted QoS 1).
144 (0x90): Topic Name invalid
Packets: CONNACK, PUBACK, PUBREC, DISCONNECT
The recipient rejects the Topic Name. For a publication, inspect its PUBLISH topic; for a refused connection, also inspect the CONNECT Will Topic. This is not limited to string-encoding errors.
- In Composer, retry a permitted exact topic.
- For CONNACK rejection, check and correct the client’s Will Topic. Compare the packets and distinguish a Topic Name from a subscription filter.
A publish Topic Name contains a wildcard. EMQX rejects this request with DISCONNECT 0x90; it is not a subscription Topic Filter.
With native max_topic_levels=1, the legal Topic Name lab/temp exceeds this broker’s depth policy. EMQX responds with DISCONNECT 0x90, not PUBACK 0x90.
This request uses lab/temp, with no wildcard or malformed Topic Name. The native depth policy causes the following DISCONNECT 0x90; no rejected PUBACK is claimed.
Correction: publish to the legal one-level Topic Name lab. The same broker policy accepts it with PUBACK 0x10 (no matching subscribers); this proves acceptance, not subscriber delivery.
148 (0x94): Topic Alias invalid
Packets: DISCONNECT
A PUBLISH uses an invalid Topic Alias, such as alias 3 when the peer allows a maximum of 2. Explicit alias value 0 is also invalid on the wire.
- Compare PUBLISH Topic Alias with the peer’s Topic Alias Maximum in Trace.
- Omit the alias and retry with the full topic. The connection form’s Topic Alias Max controls aliases received by this client.
Topic Alias 3 exceeds the advertised maximum 2. Mosquitto closes the connection with 0x94.
Before the invalid request, the real CONNACK declares Topic Alias Maximum2. The same flow later uses3 and receives DISCONNECT0x94.
This PUBLISH uses Topic Alias3, above the declared maximum2. The following real broker packet is DISCONNECT0x94; the topic text is otherwise valid.
Correction: send the full topic without a Topic Alias. Under the unchanged broker policy, this35-byte MQTT packet receives PUBACK0x10 (no matching subscribers), proving acceptance—not subscriber delivery.
154 (0x9A): Retain not supported
Packets: CONNACK, DISCONNECT
The client requested retained-message behavior from a broker that does not support it. This can involve an ordinary retained publication or Will Retain during connection.
- Inspect Retain Available in CONNACK.
- Turn Composer → Retain off and retry. For connection-stage rejection, turn off the client’s Will Retain rather than only changing the publishing form.
A retained publish reaches a broker that does not support Retain. The actual response is DISCONNECT 0x9A.
The actual CONNACK declares Retain Available=0 (No). This capability belongs to the broker; it is not a local composer preference.
The original QoS 1 PUBLISH sets Retain=true. Under the same Retain Available=0 policy, the next real broker response is DISCONNECT 0x9A.
Correction: publish with Retain=false under the unchanged broker policy. PUBACK 0x10 confirms acceptance with no matching subscribers; it does not prove delivery.
155 (0x9B): QoS not supported
Packets: CONNACK, DISCONNECT
The requested QoS exceeds broker capabilities, such as QoS 2 publishing against a QoS 1 maximum or an unsupported Will QoS. This is different from a subscription being granted a lower QoS.
- Inspect Maximum QoS in CONNACK.
- Select a supported QoS in Composer and retry. For connection rejection, check Will QoS. Confirm that the lower delivery level still meets application requirements.
The sender requests QoS 2 while the broker allows only QoS 1. The rejection is 0x9B.
The actual CONNACK declares Maximum QoS=1. The next controlled request asks for QoS 2, beyond this advertised capability.
This PUBLISH actually requests QoS 2 while the same broker declares Maximum QoS=1. The following response is DISCONNECT 0x9B.
Correction: publish at QoS 1, within the unchanged broker maximum. PUBACK 0x10 confirms acceptance with no matching subscribers, not delivery.
158 (0x9E): Shared Subscriptions not supported
Packets: SUBACK, DISCONNECT
The client requested a shared subscription such as $share/workers/lab/temp, but the broker does not support it. A successful connection does not imply shared-subscription support.
- Check Shared Subscription Available in CONNACK.
- Retry
lab/tempin the subscription form to test an ordinary subscription. This removes shared-group distribution and is not a behaviorally equivalent production replacement.
The connected client requests a shared subscription, but this broker has disabled shared subscriptions. SUBACK 0x9E rejects that operation.
The real CONNACK declares Shared Subscription Available=0. The capability is advertised before the shared-filter request; it does not disable ordinary subscriptions.
The original request uses $share/workers/lab/temp at QoS 1: workers is the share group and lab/temp is the filter. The broker responds with SUBACK 0x9E.
Correction: subscribe to ordinary lab/temp without the $share prefix. Under the same broker policy, SUBACK 0x01 grants QoS 1. No load-balanced group delivery is claimed.
161 (0xA1): Subscription Identifiers not supported
Packets: SUBACK, DISCONNECT
SUBSCRIBE included a Subscription Identifier that the server does not support. This labels a subscription; it is not a Client ID or Packet Identifier.
- Omit the optional Subscription Identifier in the client request; do not enter 0 instead of omitting it, then subscribe again.
162 (0xA2): Wildcard Subscriptions not supported
Packets: SUBACK, DISCONNECT
The filter uses + or #, such as lab/+/temp or lab/#, but the server does not support wildcard subscriptions.
- Enter an exact topic such as
lab/device01/tempin the subscription form and inspect SUBACK in Trace. - Subscribe to required topics individually and check Wildcard Subscription Available in CONNACK.
Inflight messages, size, and quotas
The wildcard filter lab/+/temp reaches a broker configured not to support wildcard subscriptions. The result is SUBACK 0xA2.
The real CONNACK declares Wildcard Subscription Available=0. Specific topic filters remain possible; this property does not imply a broker outage.
The legal filter lab/+/temp contains the single-level + wildcard. The unchanged broker policy rejects it with SUBACK 0xA2, not a malformed-filter code.
Correction: subscribe to specific lab/device01/temp without a wildcard. Under the same policy, SUBACK 0x01 grants QoS 1; it proves subscription acceptance, not message delivery.
145 (0x91): Packet Identifier in use
Packets: PUBACK, PUBREC, SUBACK, UNSUBACK
A new operation reused a Packet Identifier still occupied by an unfinished operation. This is not a Client ID or an application message ID; a legitimate retransmission is not automatically an error.
- Inspect identifiers and acknowledgements for the same session and sending direction in Trace or PCAP.
- Fix allocation or session state. Use Clean Start only when discarding previous subscriptions and pending session state is acceptable.
Packet ID 1 is reused before the first QoS 2 exchange finishes. PUBREC 0x91 rejects the conflicting request.
The original QoS 2 request reuses Packet ID 1 with DUP=false before the earlier exchange completes. The same connection contains no PUBREL/PUBCOMP between these requests; the broker’s second PUBREC is 0x91. This is not labelled a legal DUP retransmission.
The first PUBREC 0x10 belongs to Packet ID 1 and does not complete QoS 2 by itself. The full original flow shows two PUBLISH messages and two PUBREC replies, but no PUBREL/PUBCOMP completing the first exchange before the 0x91 response.
146 (0x92): Packet Identifier not found
Packets: PUBREL, PUBCOMP
The recipient cannot find the corresponding QoS 2 state. This can occur during recovery and does not alone prove a connection fault or a lost application message.
- Inspect PUBLISH → PUBREC → PUBREL → PUBCOMP for the same session in Trace or PCAP.
- Check Session Present on reconnection. Do not immediately republish and risk an application duplicate.
EMQX cannot find the QoS 2 state for Packet ID 77 and returns PUBCOMP 0x92. This alone does not establish business-message loss.
147 (0x93): Receive Maximum exceeded
Packets: DISCONNECT
Too many QoS 1/2 publications are in flight before the required acknowledgements complete. Receive Maximum is a concurrency window, not messages per second or payload size.
- Compare Receive Maximum in CONNECT/CONNACK with the acknowledgement flow in Trace.
- Reduce sender-side inflight concurrency. The client form’s Receive Max advertises its own receiving capacity, not the broker’s.
The broker declares Receive Maximum 1. Sending two QoS 2 publishes before handling their acknowledgements triggers DISCONNECT 0x93.
The real CONNACK declares Receive Maximum=1. This is the broker’s incoming QoS 1/2 window, not a messages-per-second limit or the client’s receive setting.
The sender sends two QoS 2 messages without completing either exchange. This second PUBLISH uses Packet ID 2 while ID 1 is still pending; the broker sends DISCONNECT 0x93.
The capture includes PUBREC 0x10 for Packet ID 1, but no PUBREL/PUBCOMP completes that exchange. The second QoS 2 PUBLISH uses ID 2 and the broker replies DISCONNECT 0x93. A positive PUBREC does not by itself finish QoS 2.
149 (0x95): Packet too large
Packets: CONNACK, DISCONNECT
The complete MQTT packet exceeds the receiver’s limit, including topic, properties, and headers. A 2,048-byte payload already exceeds a 1,024-byte packet limit before overhead is added.
- Inspect the peer’s Maximum Packet Size in Trace.
- In Composer, keep topic and QoS unchanged and try
{"ok":1}. Then reduce the original message. Local send rejection is not proof of a broker-issued reason code.
The full MQTT packet exceeds the broker’s 1024-byte limit. DISCONNECT 0x95 confirms a protocol-level rejection, not a local send validation.
The actual CONNACK advertises Maximum Packet Size1024 bytes. The limit applies to the whole MQTT packet, not only its payload.
Bytes1500/1524 distinguishes payload size from the complete MQTT packet.1524 exceeds the unchanged1024-byte limit; the next real broker response is DISCONNECT0x95.
Correction: this5-byte payload makes a28-byte MQTT packet, below the same1024-byte limit. PUBACK0x10 confirms acceptance with no matching subscribers, not delivery.
150 (0x96): Message rate too high
Packets: DISCONNECT
The recipient considers the arrival rate too high. Short scheduling intervals or several publishers together may exceed its accepted rate. This differs from the inflight window in 0x93.
- Stop scheduled publishing or load tests and lower the publishing rate.
- Lengthen the interval or reduce concurrent publishers according to the broker’s actual rate policy.
151 (0x97): Quota exceeded
Packets: CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT
An implementation or administrative quota was exceeded, such as a subscription or message-related allowance. The code alone does not identify the quota.
- Use Trace to identify the rejected CONNECT, PUBLISH, or SUBSCRIBE and inspect Reason String.
- Consult broker logs, remove unneeded test resources or adjust the quota, then retry the same operation.
This Mosquitto example rejects the second in-flight QoS 2 publish with PUBREC 0x97. Read the actual acknowledgement: it did not send 0x93.
With EMQX’s native subscription limit set to one, lab/first is granted and lab/second receives SUBACK0x97. This example is a subscription quota, not a generic explanation for every 0x97 response. No Reason String was attached.
159 (0x9F): Connection rate exceeded
Packets: CONNACK, DISCONNECT
Too many connections are being attempted within the allowed period, for example during a reconnect surge. This is not the total concurrent-connection limit or the publish rate.
- Stop bulk connection tests and check the original client for reconnect loops.
- Use increasing retry delays with jitter and recover within the broker’s connection-rate policy.
Packet format and other errors
128 (0x80): Unspecified error
Packets: CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
A connection, publication, or subscription failed without a more specific explanation. The code does not by itself establish bad credentials or broker overload.
- Open the failed packet in Trace, check for a Reason String, and note the preceding request and timestamp.
- Retry a minimal version of that operation and correlate it with broker logs.
This controlled empty-Client-ID request received CONNACK 0x80, not 0x85. The code alone is unspecified; use the recorded request and broker policy to investigate.
129 (0x81): Malformed Packet
Packets: CONNACK, DISCONNECT
The MQTT packet has invalid encoding or structure, such as an incorrect length, fixed-header flags, or string encoding. This is different from invalid JSON inside a payload.
- Import a decodable capture from the original device into PCAP and inspect the preceding packet.
- Compare with the same normal operation in Connections. Fix or update the faulty packet encoder or decoder, not the reconnect interval.
A controlled sender uses reserved QoS bits 3 in a PUBLISH after a successful connection. Mosquitto returns DISCONNECT 0x81. This is a malformed MQTT packet, not invalid JSON content; the original request bytes are retained in the capture.
130 (0x82): Protocol Error
Packets: CONNACK, DISCONNECT
The exchange violates protocol rules, for example by sending another CONNECT on an already established network connection. Parseable bytes can still be invalid in the current protocol state.
- Inspect packet order for the same connection in Trace or PCAP.
- Remove duplicate connection logic and retest with one client instance. A custom client needs its state machine corrected.
Repeated Payload Format Indicator properties violate the protocol. Mosquitto responds with DISCONNECT 0x82.
On the same established TCP connection, a second CONNECT follows the successful CONNACK. EMQX rejects this protocol sequence with DISCONNECT 0x82; a normal reconnect on a new socket is not equivalent.
131 (0x83): Implementation specific error
Packets: CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
The request is valid at the protocol level but is rejected by the recipient’s implementation. Its exact cause needs implementation-specific information.
- Record any Reason String supplied by the server and the request properties. Remove optional properties for a controlled comparison.
- Provide the smallest reproducible request and broker version to its maintainer.
153 (0x99): Payload format invalid
Packets: CONNACK, PUBACK, PUBREC, DISCONNECT
The payload does not match its Payload Format Indicator, for example invalid UTF-8 bytes declared as UTF-8 text. This is not a generic JSON validation code; CONNACK rejection can concern the Will Payload.
- Check that the Payload Format Indicator matches the actual payload bytes.
- Correct UTF-8 text or omit the UTF-8 claim for binary data. Check the Will Payload if connecting fails.
Success and authentication progress
These 8 distinct values are outside the failure-code range starting at 0x80. The three packet-specific names for 0x00 are explained together. MQTT 5.0 §2.4
0 (0x00): Success / Normal disconnection / Granted QoS 0
Packets: CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH, DISCONNECT, SUBACK
Not an error: CONNACK accepts the connection, DISCONNECT closes it normally, and SUBACK grants QoS 0. Other acknowledgements confirm their corresponding step.
- Check the packet type and direction in Trace.
- For a disconnect, identify its sender. For a successful publish acknowledgement, still inspect the subscriber’s received PUBLISH before concluding that the subscriber received the message.
This received CONNACK 0x00 confirms that Mosquitto accepted the connection. Check the packet type before interpreting the same numeric value in another acknowledgement.
In this SUBACK, 0x00 grants QoS0 for lab/qos0-proof. The same number means successful connection in CONNACK and normal disconnection in DISCONNECT; always read the packet type.
1 (0x01): Granted QoS 1
Packets: SUBACK
The subscription was accepted with a maximum QoS of 1. It is not a connection error, and received messages can have a lower QoS.
- Compare SUBSCRIBE with SUBACK in Trace to identify the accepted Topic Filter.
- Continue observing received PUBLISH packets; this code does not require a reconnect.
The first return value in this SUBACK is 0x01: the lab/qos1 subscription was accepted at maximum QoS 1. This is a successful subscription, not a connection error.
2 (0x02): Granted QoS 2
Packets: SUBACK
The subscription was accepted with a maximum QoS of 2. This does not certify exactly-once processing by an application database.
- Inspect SUBACK and the actual PUBLISH QoS in Trace.
- To verify application deduplication, also check the consumer’s processing results rather than relying only on MQTT acknowledgements.
SUBACK 0x02 grants maximum QoS 2 for this subscription. This does not establish exactly-once processing by the application.
SUBACK 0x02 grants QoS 2 for lab/qos2. It is a subscription result, not a payload delivery receipt; the following figures show actual delivery and its handshake.
The Mqttable subscriber actually receives qos2-receipt-proof on lab/qos2 at QoS 2. Its own PUBLISH/PUBREC/PUBREL/PUBCOMP exchange is visible—not inferred from the publisher’s ACK alone.
The subscriber sends PUBCOMP after PUBREL, completing its QoS 2 exchange. Keep its packet ID and direction together; the external publisher’s separate exchange used packet ID 7.
4 (0x04): Disconnect with Will Message
Packets: DISCONNECT
The client requests disconnection and publication of its configured Will under the Will rules. This is not a credential error, and publication need not be immediate.
- Confirm the client sent
0x04in Trace. - Observe the Will Topic with a separate subscriber and check the original client’s disconnect logic and Will Delay. Do not assume the ordinary Disconnect button sends this code.
The client sends DISCONNECT 0x04 after configuring a Will. This frame requests Will publication; the screenshot alone does not prove a subscriber received it.
The subscriber really receives will-proof-04 after the publisher sends DISCONNECT0x04. The same test configured Will Delay2s and Session Expiry30s; the paired capture preserves those settings and the actual receipt timestamp, without claiming an exact2s wall-clock interval.
The original CONNECT retains Will Delay2s and Session Expiry30s for lab/will/04. The trace includes the client-originated DISCONNECT at02:25:48.658; the companion Connections figure shows receipt at02:25:50.078. These are actual timestamps, not a claim of an exact2s measured delay.
16 (0x10): No matching subscribers
Packets: PUBACK, PUBREC
The broker accepted the publication but found no matching subscribers. This is not a publish failure; the broker may return 0x00 instead.
- Connect a second test Client ID in Connections, subscribe to the same topic, and wait for a successful SUBACK before publishing.
- Verify the subscriber’s PUBLISH in Trace, not just a change in reason code.
PUBACK 0x10 means no matching subscribers. It is not a publish failure; the broker accepted this message.
Correction: add the lab/nobody/probe subscription. This time Mqttable actually receives subscriber-present-proof and acknowledges it. Publisher acceptance alone is not used as delivery proof.
17 (0x11): No subscription existed
Packets: UNSUBACK
The current session has no subscription with that Topic Filter. For example, subscribing to lab/# does not create an exact lab/temp subscription to remove.
- Compare SUBSCRIBE and UNSUBSCRIBE in Trace and use the original complete Topic Filter.
- Confirm the same client and session are selected. A reconnect is normally unnecessary.
UNSUBACK 0x11 reports that this Topic Filter was not subscribed in the current session.
24 (0x18): Continue authentication
Packets: AUTH
Enhanced authentication requires another exchange. This is neither a failure by itself nor proof that connection or publishing has been authorized.
- Follow AUTH packets and the final outcome in Trace.
- Match the client’s Authentication Method to the server. If progress stops, check whether the original client implements the next step of that method.
The initial SCRAM-SHA-256 exchange uses AUTH0x18 to continue authentication and then receives CONNACK0x00; the server signature was verified. Auth Data is explicitly covered for privacy without changing protocol values. This is progress, not an error.
25 (0x19): Re-authenticate
Packets: AUTH
An already connected client starts re-authentication using the connection’s authentication method. This is not a server notification that the client has been disconnected.
- Check AUTH direction and the subsequent outcome in Trace.
- If a disconnect follows, inspect its actual failure code. Do not interpret
0x19itself as bad credentials or an instruction to reconnect.
The client initiates reauthentication with AUTH0x19 on the established connection, and EMQX replies AUTH0x18. No final response was obtained in this bounded test; this proves initiation and continuation, not completed reauthentication. Auth Data is hidden for privacy.
MQTT 3.1.1 return codes
CONNACK uses 0x00 for success and 0x01 to 0x05 for connection refusal. SUBACK uses 0x00, 0x01, and 0x02 for granted QoS, and 0x80 for failure. MQTT 3.1.1 has no server DISCONNECT reason codes equivalent to MQTT 5. MQTT 3.1.1 standard
0 (0x00): Connection accepted / Granted QoS 0
Packets: CONNACK, SUBACK
This is not an error. In CONNACK it accepts the connection; in SUBACK it grants QoS 0 for the corresponding subscription.
- Open the packet in Connections → Trace → Grid.
- If messages are missing, inspect SUBACK and the subscriber’s received PUBLISH. A successful connection alone does not prove delivery.
For MQTT 3.1.1, CONNACK 0x00 means the connection was accepted. The second screenshot separately shows the successful QoS 0 subscription acknowledgement.
The same value 0x00 in MQTT 3.1.1 SUBACK means this subscription was granted maximum QoS 0. Match the return value to its Topic Filter before interpreting it.
1 (0x01): Unacceptable protocol version / Granted QoS 1
Packets: CONNACK, SUBACK
In CONNACK the broker rejects the MQTT protocol version. In SUBACK the same value is successful: QoS 1 was granted.
- Check the packet type in Trace first.
- For CONNACK, edit the client’s MQTT version, select a version the broker supports, and reconnect. SUBACK needs no fix.
This listener explicitly allows only MQTT 5. Its MQTT 3.1.1 CONNACK 0x01 is a version rejection; SUBACK 0x01 has a different successful meaning.
For MQTT 3.1.1, SUBACK 0x01 grants this subscription at QoS1. It is successful and has a different meaning from CONNACK 0x01, which rejects the protocol version.
2 (0x02): Identifier rejected / Granted QoS 2
Packets: CONNACK, SUBACK
In CONNACK the Client ID is unacceptable, for example because of its length or allowed characters. In SUBACK it grants QoS 2.
- For a rejected connection, edit Client ID to a permitted nonempty identifier and reconnect.
- Try
mqttablecheck01only when the test account permits arbitrary IDs; never borrow a production device’s identity.
Mosquitto rejects the empty Client ID with MQTT 3.1.1 CONNACK 0x02. The loopback endpoint identifies this unnamed test connection; it is not a Client ID.
MQTT 3.1.1 SUBACK 0x02 grants QoS2 for this subscription. It is not the rejected-Client-ID meaning of CONNACK 0x02; the packet type determines the interpretation.
3 (0x03): Server unavailable
Packets: CONNACK
The broker received the connection request but cannot provide MQTT service. This code alone does not identify a Wi-Fi or cable failure.
- Save CONNACK and its timestamp from Trace, then check broker health and logs.
- Retry after service recovery instead of repeatedly pressing Connect.
During native EMQX evacuation, the MQTT 3.1.1 request receives CONNACK 0x03. TCP connected and a broker reply arrived; this differs from ECONNREFUSED or a connect timeout.
4 (0x04): Bad user name or password
Packets: CONNACK
The broker rejects the supplied username or password. Check input mistakes, stale credentials, and the required credential format.
- Edit the client’s authentication details, enter the correct credentials, and reconnect.
- Inspect the new CONNACK in Trace. Do not disable TLS verification or expose passwords in screenshots.
For MQTT 3.1.1, this CONNACK 0x04 rejects the test credentials. This is different from MQTT 5 DISCONNECT 0x04 and PubSubClient -4.
This MQTT 3.1.1 form keeps the synthetic password masked. It is an unsaved settings example—not another CONNACK 0x04 or proof that corrected credentials succeeded. MQTT 3.1.1 uses these credential fields without the separate MQTT 5 enhanced-method selector.
5 (0x05): Not authorized
Packets: CONNACK
The server does not permit this client to connect. Correct credentials do not necessarily grant access under the account, device, or connection policy.
- Check Username, Client ID, and the target broker in the client form.
- Ask the administrator to check connection permissions at the failure time, then reconnect and verify CONNACK
0x00.
The Client ID is validly encoded but violates this broker’s identity policy. Its MQTT 3.1.1 refusal is CONNACK 0x05.
Correction: use allowed-permission-fix, which satisfies the same allowed- identity policy. MQTT 3.1.1 CONNACK 0x00 now accepts the connection; it does not establish publish/subscribe authorization. The separate disallowed-ID request still receives 0x05.
128 (0x80): Subscription failure
Packets: SUBACK
MQTT 3.1.1 reports subscription failure without identifying the precise reason. This is not the MQTT 5 Unspecified error, despite sharing its numeric value.
- Match each SUBACK return value to its SUBSCRIBE Topic Filter in order in Trace.
- Retry one permitted exact topic and have the administrator check subscription permissions.
Authentication and CONNACK succeed, but Mosquitto’s native policy refuses the lab/denied subscription with MQTT 3.1.1 SUBACK 0x80. This is the generic subscription-failure value for this protocol, not MQTT 5’s 0x80 meaning.
Client-library error codes
These values are defined by client libraries. Match the library and version before interpreting a number using a protocol table.
PubSubClient: ESP32 / ESP8266
These are PubSubClient client.state() values, often printed as rc=-2 or rc=-4 in Arduino logs. They are not negative MQTT 5 reason codes, and other Arduino libraries may assign different meanings. Positive values 1 to 5 use the connection-return meanings in the MQTT 3.1.1 section. Definitions Connection implementation
PubSubClient -2: connection failed
Code / log: MQTT_CONNECT_FAILED / rc=-2
The underlying Arduino Client could not connect. Check the address, listener, network path, and any TLS wrapper before treating this as an MQTT credential rejection.
- Check connectivity on the ESP32/ESP8266 itself, the target address, listener port, and any TLS wrapper.
- A desktop connection does not prove the device has the same network access. Establish the lower-level connection before diagnosing MQTT authentication.
PubSubClient -4: connection timeout
Code / log: MQTT_CONNECTION_TIMEOUT / rc=-4
The client timed out waiting for a response. This can occur while waiting for the broker’s connection response or when a keep-alive ping remains unanswered. It is not CONNACK return code 4.
- Check the device’s endpoint and whether the application services its network loop. Do not just lengthen the timeout without locating the missing response.
PubSubClient -3: connection lost
Code / log: MQTT_CONNECTION_LOST / rc=-3
A previously established connection was lost. This status does not identify whether the broker, device, or network caused the loss.
- Keep the device log immediately before the loss and check broker health and device connectivity.
- Check for another client using the same Client ID, but confirm it with evidence rather than assuming every lost connection is a takeover.
PubSubClient -1: disconnected state
Code / log: MQTT_DISCONNECTED / rc=-1
The client is disconnected. This can be an initial or deliberately disconnected state, not a precise diagnosis of the preceding failure.
- Record the result and state immediately after the device’s connect attempt.
- Inspect the application’s connection lifecycle rather than searching for a broker-side -1 reason code.
Paho Python
The entries below refer specifically to paho.mqtt.enums.MQTTErrorCode. Keep it separate from ConnackCode and ReasonCode. Paho’s VERSION2 callbacks also use ReasonCode for MQTT 3 connections, with changed nonzero numeric values; seeing 135 in a callback is not proof that the wire protocol is MQTT 5. Enums · Callback migration
Paho Python 4: client is not connected
Code / log: MQTT_ERR_NO_CONN
In the MQTTErrorCode API enum, 4 means no connection. It does not mean bad credentials as CONNACK 4 does.
- Wait for a successful connection callback before dependent operations and handle subsequent disconnects.
- Compare a single publish in Mqttable Connections → Composer. If that succeeds, check the Python application’s timing and connection state.
In the actual Paho Python2.1.0 test, publish before on_connect returned MQTT_ERR_NO_CONN(4); waiting for the successful callback fixed it. This Mqttable figure is the correct lifecycle counterpart, not a product field displaying SDK4. PUBACK0x10 is successful with no matching subscribers, not proof of subscriber delivery.
Paho Python 5: connection refused
Code / log: MQTT_ERR_CONN_REFUSED
The MQTTErrorCode enum uses 5 for a refused connection. First identify whether the number came from this enum, a legacy CONNACK callback, or a ReasonCode object.
- Retain the Python callback name and full error, then compare CONNACK in Mqttable Trace.
- Only diagnose an authorization rejection when the actual response supports it; do not treat every API error 5 as a password problem.
The actual Paho Python2.1.0 test separately logs legacy on_connect value5 and loop() MQTT_ERR_CONN_REFUSED(5). The original packet is MQTT3.1.1 CONNACK5. Those equal integers belong to different APIs; connect() initially returned0, and neither figure nor callback alone establishes a universal authorization cause.
Paho Python 7: connection lost
Code / log: MQTT_ERR_CONN_LOST
MQTTErrorCode 7 reports a lost connection. There is no assigned MQTT 5 wire reason code 0x07 to look up for this API error.
- Record Python logs, connection timing, and the last exchange.
- Use an authorized Proxy or decodable PCAP to distinguish a broker response from a transport interruption. Check the original client’s network loop as well as server logs.
The actual Paho Python2.1.0 legacy callback reports on_disconnect rc7, and loop returns7, about0.52 seconds after successful on_connect. The original capture contains the later TCP RST but no MQTT DISCONNECT. This view shows the last decoded MQTT packets; its decoded-MQTT time window is not the full transport lifetime.
The original client-side capture, filtered to the single Python connection without changing timestamps or packet bytes, produces Mqttable’s native TCP reset finding. Its RST is at 00:16:01.406109 (UTC+8), after the successful handshake. This closes the transport-evidence gap; the SDK callback value 7 remains established by the Python log, not by this product field.
Paho Python 16: keepalive timeout
Code / log: MQTT_ERR_KEEPALIVE
MQTTErrorCode 16 identifies a keepalive failure. MQTT 5 PUBACK/PUBREC reason 16 (0x10) instead means no matching subscribers.
- Inspect PINGREQ/PINGRESP in the original client’s traffic and ensure its network loop is being serviced.
- Enable Trace → Heartbeat for a Mqttable comparison. Distinguish a client-detected timeout from a broker-issued 141 / 0x8D.
Paho Java
These entries refer to org.eclipse.paho.client.mqttv3.MqttException. Keep getReasonCode() together with getCause(); these five-digit values are Java-library errors, not one-byte MQTT wire codes. Exception reference · Numeric values Connection-loss report
With KeepAlive1 second, the real Paho Python2.1.0 legacy on_disconnect callback reports SDK16 after about2.14 seconds. loop returns7 separately. The controlled relay drops the actual PINGRESP; the original client-side capture has PINGREQ but no PINGRESP. SDK16 is neither PUBACK0x10 nor broker DISCONNECT0x8D.
Paho Java 32000: timed out waiting for a response
Code / log: REASON_CODE_CLIENT_TIMEOUT
The Java client timed out waiting for a response, including a keepalive response.
- Save the exception and identify the outstanding request.
- In a decodable PCAP or authorized Proxy trace, look for the corresponding reply. Separate a silent network path from an application that cannot process incoming traffic.
The actual Paho Java1.2.5 connect token waitForCompletion(1000ms) throws32000 while waiting for CONNACK. The controlled relay forwards the request but drops the real Mosquitto response. This original capture shows the waiting request; it is not a keep-alive or PUBACK timeout, and no Java exception field is inserted into Mqttable.
Paho Java 32100: client is already connected
Code / log: REASON_CODE_CLIENT_CONNECTED
The client is already connected. This is a local lifecycle problem, not a broker rejection code.
- Remove duplicate connect calls and give one component ownership of reconnects.
- A single stable Mqttable connection is a useful baseline; changing broker credentials will not fix overlapping application connect calls.
In the actual Paho Java1.2.5 test, a second connect() after success throws32100 locally. This Mqttable counterpart keeps one connected client and shows one successful handshake. It does not display a Java exception field or prove the repeated method call from packets alone.
Paho Java 32103: unable to connect to server
Code / log: REASON_CODE_SERVER_CONNECT_ERROR
The Java client could not establish its server connection; inspect the nested cause for details.
- Record
getReasonCode()andgetCause(), then compare the same endpoint and transport in Mqttable Connections. - Investigate the original host’s DNS, routing, and TLS configuration according to that cause, not the outer number alone.
The actual Java1.2.5 connection attempt reports32103 with java.net.ConnectException on unlistened loopback21999. Mqttable tests the same endpoint and stops at TCP Connection refused; no MQTT CONNACK arrived. This concrete cause is not a universal explanation for every32103.
Paho Java 32104: client is not connected
Code / log: REASON_CODE_CLIENT_NOT_CONNECTED
The operation requires a connected client. A previous connection may also have been lost.
- Wait for successful asynchronous connection completion before publishing or subscribing.
- Compare with one successful Mqttable publish, then fix the Java state transition; do not assume calling connect means an asynchronous connection has finished.
The real Paho Java1.2.5 test throws32104 when publish is called before connecting. This Mqttable counterpart waits for successful CONNACK, then subscribes and receives SUBACK1. It demonstrates the correct lifecycle, not a native Java error field.
Paho Java 32109: Connection lost / java.io.EOFException
Code / log: REASON_CODE_CONNECTION_LOST
The connection ended unexpectedly. A reported form is Connection lost (32109) - java.io.EOFException; the nested exception adds context but does not identify a unique root cause.
- Save the entire exception chain and the broker log at that time.
- Inspect device traffic in PCAP for the last MQTT exchange and connection closure; check duplicate IDs, server restarts, and the network path against that evidence.
After a successful real connection, Paho Java1.2.5 connectionLost receives32109 with java.io.EOFException when the controlled relay closes TCP with FIN. The original client capture has no MQTT DISCONNECT. This view shows the last decoded MQTT traffic; neither EOFException nor this picture establishes a unique cause for all connection loss.
This single-flow subset of the original Java capture retains the actual TCP boundary. Mqttable reports Opening SYN and FIN or RST observed. The last decoded MQTT packet is at 01:02:38.764016; the original TCP FIN follows at 01:02:39.288038 (UTC+8), with no MQTT DISCONNECT. The displayed MQTT Duration is not the TCP lifetime. The Java log separately establishes 32109 and EOFException.
Paho Java 32110: connect already in progress
Code / log: REASON_CODE_CONNECT_IN_PROGRESS
Another connection attempt is already in progress on this client.
- Serialize connection attempts and wait for their completion or failure.
- Do not let a retry timer and automatic reconnect independently start new attempts. Use Mqttable as a single-connection baseline, not as a replacement for fixing the Java state machine.
The actual Java1.2.5 program calls connect() again while the first asynchronous token is pending and gets32110; the original token later succeeds. This is the completed Mqttable connection counterpart. Local concurrent-call state is established by the Java log, not by a fabricated packet value.
Paho Java 32202: too many publishes in progress
Code / log: REASON_CODE_MAX_INFLIGHT
The Java client’s local inflight limit has been reached. This is not automatically a broker-issued 147 / 0x93.
- Reduce concurrent publishes and inspect acknowledgement completion through PCAP or Proxy.
- A single-message Mqttable test can check basic delivery. Investigate missing ACKs before increasing local inflight limits.
Qt / C-more devices
Qt MQTT defines the following four client errors; they also appear in the AutomationDirect C-more device reference. Values above 0xFF cannot fit into MQTT 5’s one-byte Reason Code field. Other clients, including Mqttable, need not display these same numbers. Reference list · Client-error definitions
The actual Java1.2.5 client configures maxInflight=1. The relay forwards its first QoS1 PUBLISH and drops the real PUBACK; the second publish() throws32202 locally before sending another PUBLISH. This is the SDK’s local window, not broker DISCONNECT0x93. Original configuration/logs establish the limit, not this picture alone.
With Java maxInflight still1, the actual corrected test sends one QoS1 message and waits for its real acknowledgement; the delivery token completes. This native Mqttable counterpart likewise receives PUBACK for a single publication. Keep the local window distinct from MQTT5 Receive Maximum.
Qt 256 (0x100): Transport error
Source: QMqttClient::ClientError, not an MQTT wire reason code. Qt error definitions
The client reports a transport problem or unexpected connection loss. This is not a reason code sent by the broker.
- Use the Qt client log and lower-level network or TLS error details to distinguish a failed connection attempt from loss of an established connection.
Qt 257 (0x101): Protocol violation
Source: QMqttClient::ClientError, not an MQTT wire reason code. Qt error definitions
The client detected a protocol violation and closed the connection. This extension code is not MQTT 5 0x81.
- Keep the original client logs and preceding packets. Check protocol compatibility between the client, server, and any intermediary.
Qt 258 (0x102): Unknown error
Source: QMqttClient::ClientError, not an MQTT wire reason code. Qt error definitions
The client could not classify the failure. The code alone cannot distinguish transport, authentication, or implementation problems.
- Record the original client version, full error log, and timestamp, then inspect any lower-level error.
- If the failure is intermittent, retain the original device records rather than only this number.
Qt 259 (0x103): MQTT 5-specific error
Source: QMqttClient::ClientError, not an MQTT wire reason code. Qt error definitions
This is a wrapper indicating an MQTT 5 failure, not the final diagnosis. A separate reason code, such as 0x87, may provide the cause.
- Inspect the Qt client’s detailed error properties, obtain the actual MQTT 5 reason code, and look it up in the MQTT 5 section.
ESP-IDF / ESP-TLS
On ESP32, the library matters: ESP-IDF transport errors are a separate code system from PubSubClient states. ESP-IDF error reference
ESP-IDF 32774 (0x8006): ESP-TLS connection timeout
Code / log: ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT / 0x8006
ESP-IDF reports a timeout while opening the lower-level connection. The enum is not an MQTT CONNACK value and does not, by itself, prove a certificate problem. It is distinct from the TLS server-handshake timeout enum 0x8009.
- Read the ESP-IDF error type and transport details together, then check the device’s endpoint and network.
- Keep this code separate from PubSubClient rc=-4 even when both involve an ESP32.
Network, TLS, and WebSocket errors
The first six entries use Node.js error names, which can appear underneath MQTT applications. WebSocket 1006 belongs to a different protocol. Diagnose the reported layer before changing MQTT credentials or QoS. Node.js errors · WebSocket close codes
TCP and DNS
ECONNREFUSED: MQTT transport connection refused
Code / log: connect ECONNREFUSED
In Node.js-style errors, the target actively refused the connection. This is different from an MQTT CONNACK authorization rejection.
- Check the broker listener, address, port, and container/network reachability.
- In Mqttable Connections, use the same transport to compare. A desktop success does not validate the DNS or routing inside the original application’s container.
The test resolves 127.0.0.1, then TCP port 21999 refuses the connection. MQTT negotiation has not started; this is a transport failure, not a CONNACK reason code. The form change is not saved.
Using the actual Mosquitto listener, the same test now receives CONNACK 0x00 for MQTT 3.1.1 and 5.0. This verifies connectivity, not publish/subscribe authorization.
ECONNRESET: MQTT connection reset by peer
Code / log: read ECONNRESET / connection reset by peer
The underlying connection was forcibly closed. The error does not identify a particular MQTT rule violation.
- Correlate the failure with broker and proxy logs.
- Inspect the correct TCP flow in PCAP; if no MQTT response is visible, keep transport failure separate from MQTT rejection. A reset alone is not proof of bad credentials.
The controlled relay resets the established TCP socket while the client waits for CONNACK. Native Client Test Connection reports Connection reset, and the original capture contains TCP RST. This is a transport interruption, not a received MQTT DISCONNECT or an authentication refusal.
ETIMEDOUT: MQTT connection or network operation timed out
Code / log: connect ETIMEDOUT
A network operation did not complete within its timeout. It is not the MQTT 5 Keep Alive reason code.
- Determine whether the timeout happened before MQTT CONNECT, during connection establishment, or on an existing connection.
- Compare Connections errors and original-device PCAP evidence; check the network path before adjusting timers.
A controlled relay forwards CONNECT to Mosquitto but drops the real return traffic. TCP succeeds; Mqttable then times out waiting for CONNACK. The current connection test uses a fixed timeout of about 10 seconds, not a configurable UI setting. This is an MQTT response timeout, not a DNS failure, TCP refusal or Keep Alive timeout.
ENOTFOUND: MQTT broker hostname could not be resolved
Code / log: getaddrinfo ENOTFOUND
The client could not resolve the hostname. MQTT username, topic, and QoS changes do not repair name resolution.
- Check the Host spelling and DNS from the original runtime.
- Compare the same hostname in Mqttable Connections, accounting for split DNS or container differences. Do not switch permanently to an IP address if that breaks TLS hostname verification.
TLS certificate validation
The reserved .invalid hostname fails during name resolution. TCP and MQTT have not started, so credentials, topics and QoS cannot explain this result. This is the desktop runtime’s DNS observation, not proof of a device’s resolver behavior.
CERT_HAS_EXPIRED: a certificate is past its validity period
Code / log: CERT_HAS_EXPIRED
Certificate validation reports an expired certificate. This is a TLS error, not an MQTT reason code.
- Check the original machine’s clock and the certificate chain, then renew the expired certificate.
- Retest TLS in Mqttable Connections with verification enabled. Disabling verification is not a production fix.
The selected test CA is trusted and the certificate matches 127.0.0.1, but its validity has ended. The real TLS result is certificate_expired with Verify ON. No system clock changes or verification bypasses were used.
Keep server identity verification enabled and trust only the test CA for this isolated endpoint. The test uses server TLS validation; client-certificate authentication (mTLS) is off.
The expired server certificate is replaced on the same Mosquitto listener and reloaded. The unchanged host, trusted CA and enabled verification now pass TLS and receive CONNACK 0x00.
ERR_TLS_CERT_ALTNAME_INVALID: broker address and certificate do not match
Code / log: ERR_TLS_CERT_ALTNAME_INVALID
The hostname or IP does not match the certificate’s subject alternative names.
- Use the intended broker hostname covered by its certificate, or issue a matching certificate.
- Verify the corrected Host and TLS settings in Mqttable Connections; do not bypass hostname validation to hide the mismatch.
WebSocket
The CA and certificate dates are valid, but 127.0.0.1 is absent from the server certificate SAN. Mqttable reports hostname_check_failed and shows the requested address and received localhost name. Verification stays enabled.
The hostname-mismatch test keeps Verify server identity enabled and uses the valid test CA. Do not disable verification to silence the failure; correct the address or certificate SAN.
On the same TLS listener and unchanged certificate, using localhost matches its SAN. The tests now succeed and receive CONNACK 0x00 without disabling verification.
1006: abnormal closure without a Close frame
Code / log: WebSocket close code 1006
The endpoint reports abnormal closure without receiving a WebSocket Close frame. The reserved value 1006 is not sent in a Close frame and is not an MQTT reason code.
- Check the original browser’s handshake, WS/WSS endpoint, and reverse-proxy logs.
- Compare the same WebSocket endpoint in Mqttable Connections, then distinguish WebSocket failure from MQTT rejection; native-client success does not validate every browser policy.
The original browser test opened this WebSocket endpoint and received CONNACK, then reported close code 1006 with wasClean=false after a TCP reset without a Close frame. Mqttable’s same-endpoint observation is a SYSTEM closure event, not a received MQTT DISCONNECT and not a product field containing 1006. Repeated retries were stopped after collecting the evidence.
Collect evidence and verify the fix
The examples in this guide use Mqttable, the MQTT workbench published by this site. You can follow the same checks in your client logs and broker logs. UI names refer to Mqttable’s English interface.
Find the original response in Trace
Find the response in Mqttable: open Connections → your Broker → Trace → Grid, clear Topic/Payload filters, select the client, and open the response. Check its type, direction, and reason. Enable Heartbeat for PING packets; a filtered-out packet is not evidence of a missing response. Trace guide
For an external device, use its logs, a decodable PCAP , or authorized traffic through Proxy . Connections Trace does not automatically observe other applications. Compare the same endpoint and transport using a separate authorized test identity; a successful desktop test does not prove the original device has identical DNS, routing, or TLS settings. These checks are diagnostic suggestions, not per-code runtime test results.
When there is no reason code
A missing MQTT reason code does not mean there was no failure. Check connection errors in Connections and the final Trace rows, then correlate device logs and PCAP evidence for TCP closure, TLS handshake failure, or network loss. An encrypted TLS capture alone does not imply that Mqttable can read the MQTT reason code inside it. PCAP boundaries
After a fix, repeat the operation that originally failed: check CONNACK for connection acceptance, SUBACK for subscription acceptance, publication acknowledgements and subscriber reception for delivery, or connection stability under the original disconnect trigger. A Connected indicator alone is not sufficient verification. Publishing and verification
What to include when asking for help
- The client library and version, MQTT version, and complete error text.
- The failed operation, packet type and direction, timestamp, and relevant broker log.
- The endpoint and transport, plus whether the failure also occurs from the original device or container.
Redact passwords, tokens, private keys, and sensitive payloads before sharing logs or captures. Record what changed and whether the original operation now succeeds.
Protocol values follow the MQTT 5.0 and MQTT 3.1.1 standards. Client and network codes use the official sources linked in their sections. The steps are diagnostic suggestions, not claims that every code was reproduced in Mqttable.