DATA SHEET
Next-Gen MQTT Platform for IoV and Automotive Innovation →

MQTT Reason Code Introduction and Quick Reference

EMQX Team
Jun 19, 2023
MQTT Reason Code Introduction and Quick Reference

Reason Code

The primary purpose of Reason Code in MQTT is to provide more detailed feedback to the client and server. For example, we can feed back the Reason Code corresponding to the wrong username or password to the client in the CONNACK packet, so that the client can know why it cannot connect.

Reason Code in MQTT 3.1.1

Although MQTT 3.1.1 already supports Reason Code, it doesn't define many available Reason Codes. In fact, they are very limited.

Among the two MQTT packets that support Reason Code, the CONNACK packet has only 5 Reason Codes to indicate failures. And the SUBACK packet has only one Reason Code for indicating failure, it cannot even provide further details about the reason for the subscription failure. Moreover, for operations such as publishing and unsubscribing that don't support Reason Code, we can't even determine whether the operation was successful or not. This makes development debugging unfriendly and hinders the implementation of robust code.

Reason Code in MQTT 5.0

So In MQTT 5.0, the number of available Reason Codes has been expanded to 43, and it is specified that Reason Codes below 0x80 are used to indicate success, while Reason Codes greater than or equal to 0x80 are used to indicate failure. Unlike MQTT 3.1.1, where Reason Codes below 0x80 could also indicate failure. This allows clients to determine whether an operation was successful or not quickly.

Furthermore, MQTT 5.0 extends the support for Reason Codes to the following packets: CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, and AUTH. Now, we can not only determine if a message publication was successful but also understand the reasons for failure, such as the absence of matching subscribers or insufficient privileges to publish to a specific topic.

Reason Code in MQTT 5.0

Most MQTT packets include only a single Reason Code, except for SUBACK and UNSUBACK. This is because the SUBSCRIBE and UNSUBSCRIBE packets can contain multiple topic filters, and each topic filter must have a corresponding Reason Code to indicate the result of the operation. Therefore, SUBACK and UNSUBACK packets need to accommodate multiple Reason Codes. That's why Reason Codes in other packets are located in the Variable Header, while the Reason Codes in SUBACK and UNSUBACK are located in the Payload.

MQTT packets

In this article's final Reason Code quick reference table, we have provided detailed explanations and use cases for each Reason Code in MQTT 5.0. You can take a look at it for more information.

Indicates to the client why the connection was disconnected

In MQTT 3.1 and 3.1.1, the DISCONNECT packet could only be sent by the client. Therefore, when a client violated certain restrictions, the server could only directly close the network connection without providing additional information to the client. This made it challenging to investigate the reason for the disconnection.

Now in MQTT 5.0, the server can send a DISCONNECT packet to the client before closing the network connection. The client can use the Reason Code in the DISCONNECT packet to get why the connection was disconnected, such as the packet being too large, the server being busy, and so on.

Reason String

Reason String is a complement to Reason Code in MQTT 5.0, providing a human-readable string designed for diagnostic purposes. While Reason Code can indicate most error reasons, developers or operators may still need more intuitive contextual information.

For example, when the server indicates an invalid topic filter to the client using the Reason Code (0x8F), developers still have no specific information about the reason. Is it due to exceeding the maximum number of topic levels or including characters not accepted by the server? However, if the server can return a Reason String similar to "The number of topic levels exceeds the limit, the maximum is 10," developers can quickly understand the reason and make adjustments.

In practical use, the content of the Reason String depends on the specific implementation of the client and server. Therefore, a correctly implemented receiving end should not attempt to parse the content of the Reason String. Recommended usage includes but is not limited to using the Reason String when throwing exceptions or writing it to logs.

Finally, Reason String is an optional feature, and whether a Reason String is received depends on whether the peer supports it.

MQTT 5.0 Reason Code Quick Reference Table

Reason Code Name Packets Details
0x00 (0) Success CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH This Reason Code can be used in all packets with Reason Code, such as CONNACK, DISCONNECT packet, etc. It is usually used to indicate success, such as successfully connected, successfully unsubscribed, successfully received packets, successfully authenticated, and so on.
0x00 (0) Normal disconnection DISCONNECT In the DISCONNECT packet, a Reason Code of 0 indicates a regular disconnection, where the Will Message will not be published.
0x00 (0) Granted QoS 0 SUBACK 0, 1, and 2 in the SUBACK packet are used to indicate the subscription result. They all represent a successful subscription, and at the same time, they indicate the maximum QoS level granted to the subscriber. 0, 1, and 2 exactly correspond to three QoS levels.This is because the maximum QoS level granted by the server may be smaller than the maximum QoS level requested when subscribing. For example, if the maximum QoS level requested during subscription is 2, but the server only supports QoS 1, etc.
0x01 (1) Granted QoS 1 SUBACK -
0x02 (2) Granted QoS 2 SUBACK -
0x04 (4) Disconnect with Will Message DISCONNECT Only used for DISCONNECT packets, and it is suitable for situations where the client wants to disconnect normally, but the server still needs to publish a will message. For example, the clients want to be notified of session expiration.
0x10 (16) No matching subscribers PUBACK, PUBREC This Reason Code is used to indicate to the sender that the message has been received, but there are currently no matching subscribers, so only the server can use this Reason Code. We can know that no one will receive our message when we receive a response packet with Reason Code 0x10, but we cannot assume that everyone will receive our message when we do not receive a response packet with Reason Code 0x10, unless there will be at most one subscriber. But note that using 0x10 instead of 0x00 when there are no matching subscribers is not a mandatory behavior, it depends on the specific implementation of the server.
0x11 (17) No subscription existed UNSUBACK Only used for UNSUBACK packets, indicating that no matching subscription was found when unsubscribing.
0x18 (24) Continue authentication AUTH Only used for AUTH packets, indicating to continue authentication. Through this Reason Code, the client and server can exchange AUTH packets any number of times to meet the needs of different authentication methods.
0x19 (25) Re-authenticate AUTH Only used for AUTH packets. After enhanced authentication is successful, the client can initiate re-authentication at any time by sending an AUTH packet with Reason Code 0x19. During re-authentication, other packet sending and receiving will continue normally. If re-authentication fails, the connection will be closed.
0x80 (128) Unspecified error CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT Indicates an unspecified error. When one party does not wish to disclose the specific cause of the error to the other party, or no Reason Code can match the current situation in the protocol specification, it can use this Reason Code in the packet.
0x81 (129) Malformed Packet CONNACK, DISCONNECT Indicates that the received packet cannot be correctly parsed according to the protocol specifications. In MQTT, we refer to these types of packets as malformed packets.
0x82 (130) Protocol Error CONNACK, DISCONNECT Protocol errors usually refer to errors that can be discovered only after the control packet is parsed according to the protocol specifications, including data that the protocol does not allow, behavior that does not conform to the protocol requirements, and so on. For example, the client sends two CONNECT packets within a single connection.
0x83 (131) Implementation specific error CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT The packet is valid, but not accepted by the current receiver's implementation.
0x84 (132) Unsupported Protocol Version CONNACK Only used for CONNACK packets, indicating that the server does not support the MQTT protocol version requested by the client.
0x85 (133) Client Identifier not valid CONNACK Only used for CONNACK packets, indicating that the Client ID is valid, but is not accepted by the server. For example, the Client ID exceeds the maximum length allowed by the server.
0x86 (134) Bad User Name or Password CONNACK Only used for CONNACK packets, indicating that the client was refused a connection because it used an incorrect username or password.
0x87 (135) Not authorized CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT Indicates that the operation is not authorized. For example, the client does not have permission to publish messages to the corresponding topic.
0x88 (136) Server unavailable CONNACK Only used for CONNACK packets, indicating to the client that the server is currently unavailable. For example, the current server authentication service is abnormal and cannot accept new clients.
0x89 (137) Server busy CONNACK, DISCONNECT Indicates to the client that the server is busy, please try again later.
0x8A (138) Banned CONNACK Only used for CONNACK packets, indicating that the client is banned from logging in. For example, the server detects abnormal connection behavior from the client, so it adds the client's Client ID or IP address to the blacklist, or the background administrator manually bans the client. Of course, these usually depend on the specific implementation of the server.
0x8B (139) Server shutting down DISCONNECT Only used for DISCONNECT packets, and only the server can use it. If the server is in the process of or about to shut down, it can inform the client that the connection is terminated because the server is shutting down by actively sending a DISCONNECT packet with Reason Code 0x8B. This can help clients avoid continuing to initiate connection requests to this server after the connection is closed.
0x8C (140) Bad authentication method CONNACK, DISCONNECT When the server does not support the enhanced authentication method specified by the client, or the client uses a different authentication method than the previous authentication during re-authentication, the server will send a CONNACK or DISCONNECT packet with Reason Code 0x8C.
0x8D (141) Keep Alive timeout DISCONNECT Only used for DISCONNECT packets, and only the server can use it. The server closed the connection because it did not receive any packets within 1.5 times the Keep Alive time.
0x8E (142) Session taken over DISCONNECT Only used for DISCONNECT packets, and only the server can use it. Another more recent connection using the same Client ID was established, causing the server to close this connection.
0x8F (143) Topic Filter invalid SUBACK, UNSUBACK, DISCONNECT The Topic Filter is in the correct format, but is not accepted by the server. For example, the level of Topic Filters exceeds the maximum number allowed by the server.
0x90 (144) Topic Name invalid PUBACK, PUBREC, DISCONNECT The Topic Name is in the correct format, but is not accepted by the client or server.
0x91 (145) Packet identifier in use PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT The Packet ID in the received packet is in use. This usually means that the session state of the client and server do not match, or that one of them has an incorrect implementation.
0x92 (146) Packet Identifier not found PUBREL, PUBCOMP Only used for PUBREL and PUBCOMP packets, indicating that the Packet ID in the received packet is not found. This usually means that the session state of the client and server do not match, or that one of them has an incorrect implementation.
0x93 (147) Receive Maximum exceeded DISCONNECT Only used for DISCONNECT packets, indicating that the maximum receive value has been exceeded. MQTT 5.0 adds a flow control mechanism. When connecting, the client and server agree on the number of reliable messages that can be processed simultaneously through the Receive Maximum property (QoS > 0). Therefore, when the number of unconfirmed messages sent by the sender exceeds this limit, the receiver will send a DISCONNECT packet with Reason Code 0x93 and close the network connection.
0x94 (148) Topic Alias invalid DISCONNECT Only used for DISCONNECT packets, indicating that the Topic Alias is invalid. If the Topic Alias value in the PUBLISH packet is 0 or greater than the maximum Topic Alias agreed upon at the time of connection, the receiver will consider this a protocol error and send a DISCONNECT packet with Reason Code 0x94 and close the network connection.
0x95 (149) Packet too large CONNACK, DISCONNECT The packet exceeds the maximum allowable size agreed upon at the time of connection.
0x96 (150) Message rate too high DISCONNECT Only used for DISCONNECT packets, indicating that the message rate is too high. The server may limit the message rate of the client, for example, allowing a maximum of 100 messages per second. When the client exceeds this limit, the server will send a DISCONNECT packet with Reason Code 0x96 and close the network connection.
0x97 (151) Quota exceeded CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT Used to indicate that a quota limit has been exceeded. The server may limit the sending quota of the publisher, such as allowing a maximum of 1000 messages to be forwarded daily. When the publisher exhausts the quota, the server will use this Reason Code in acknowledgment packets such as PUBACK to remind the publisher. On the other hand, the server may also limit the number of connections and subscriptions of the client. When this limit is exceeded, the server will indicate to the client through CONNACK or SUBACK packets that the current quota has been exceeded. Some strict clients and servers may choose to send a DISCONNECT packet and close the connection when they detect that the peer has exceeded the quota.
0x98 (152) Administrative action DISCONNECT Only used for DISCONNECT packets, indicating to the client that the connection was closed due to a management operation, such as an administrator kicking out the client connection in the background.
0x99 (153) Payload format invalid PUBACK, PUBREC, DISCONNECT Indicates that the format of the Payload does not match the format indicated by the Payload Format Indicator property.
0x9A (154) Retain not supported CONNACK, DISCONNECT The server does not support retained messages.
0x9B (155) QoS not supported CONNACK, DISCONNECT The server does not support the QoS level requested by the client.
0x9C (156) Use another server CONNACK, DISCONNECT The server is temporarily unable to serve the client, and the client should try to connect to another server.
0x9D (157) Server moved CONNACK, DISCONNECT The server has moved to another address, and the client should try to connect to the new address.
0x9E (158) Shared Subscriptions not supported SUBACK, DISCONNECT The server does not support shared subscriptions.
0x9F (159) Connection rate exceeded CONNACK, DISCONNECT The server has exceeded the maximum number of connections it can handle, and the client should try to connect to another server.
0xA0 (160) Maximum connect time DISCONNECT Only used for DISCONNECT packets, and only the server can use it. For security reasons, the server can limit the maximum connection time of the client for a single authentication. For example, when using JWT authentication, the client connection should not continue after the JWT expires. In this case, the server can send a DISCONNECT packet with Reason Code 0xA0 to indicate to the client that the connection was closed because the maximum allowed connection time has been exceeded. After receiving a DISCONNECT packet with this Reason Code, the client can re-obtain the authentication credentials and request a connection again.
0xA1 (161) Subscription Identifiers not supported SUBACK, DISCONNECT The server does not support subscription identifiers, but the client's subscription request contains subscription identifiers. The server can either reject the subscription request by sending a SUBACK packet with Reason Code 0xA1, or directly send a DISCONNECT packet with Reason Code 0xA1 and close the network connection.
0xA2 (162) Wildcard Subscriptions not supported SUBACK, DISCONNECT The server does not support wildcard subscriptions.
Try EMQX Cloud for Free
A fully managed MQTT service for IoT
Get Started →

Related Posts

Jul 8, 2023EMQX Team
MQTT Control Packets: A Beginner's Guide

As the smallest data unit in MQTT, MQTT control packets facilitate tasks like subscribing to topics and publishing messages between clients and servers.