Webinar
Unifying Data from Vehicle to Cloud | Register Now →

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 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 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 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 Granted QoS 1 SUBACK -
0x02 Granted QoS 2 SUBACK -
0x04 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 No matching subscribers PUBACK, PUBREC This reason Code is used to indicate to the sender that the message has been received, but there is currently no matching subscriber, so only the server can use this Reason Code.We can know that no one will receive our message by receiving a response packet with a Reason Code of 0x10, but we cannot assume that everyone will receive our message by not receiving a response message with Reason Code 0x10, unless there will be at most one subscriber.But it should be noted that using 0x10 instead of 0x00 when there is no matching subscriber is not a mandatory behavior, it depends on the specific implementation of the server.
0x11 No subscription existed UNSUBACK Only used for UNSUBACK packets, indicating that no matching subscription was found when unsubscribing.
0x18 Continue authentication AUTH Only used for AUTH packets, which means continuing authentication. Through this Reason Code, any number of AUTH packets can be exchanged between the client and the server to meet the needs of different authentication methods.
0x19 Re-authenticate AUTH Only used for AUTH packets. After the 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, the sending and receiving of other packets will continue normally. If re-authentication fails, the connection will be closed.
0x80 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 Malformed Packet CONNACK, DISCONNECT When receiving a control packet that cannot be correctly parsed according to the protocol specification, the receiver must send a DISCONNECT packet with Reason Code 0x81 to disconnect. If there is a problem with the CONNECT packet, the server should use the CONNACK packet.When the reserved bit in the fixed header is not set to 0 according to the protocol requirements, the QoS is specified as 3, and the UTF-8 string contains a null character in the control packet, it will be considered a malformed packet.
0x82 Protocol Error CONNACK, DISCONNECT Errors detected after the control packet is parsed according to the protocol specification, such as data not allowed by the protocol, behavior inconsistent with the protocol requirements, etc., will be considered protocol errors.The receiver must send a DISCONNECT packet with Reason Code 0x81 to disconnect. If there is a problem with the CONNECT packet, the server should use the CONNACK packet.Common protocol errors include the client sending two CONNECT packets within one connection, one packet containing multiple identical properties, a property being set to a value not allowed by the protocol, etc.But when we have other more specific Reason Codes, we will not use 0x81 (Malformed Packet) or 0x82 (Protocol Error).For example, the server has declared that it does not support retained messages, but the client still sends retained messages to the server, which is essentially a protocol error, but we will choose to use 0x9A (Retain not supported), which can more clearly indicate the cause of the error.
0x83 Implementation specific error CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT The packet is valid, but not accepted by the current receiver's implementation.
0x84 Unsupported Protocol Version CONNACK Only used for CONNACK packets. For the server that supports MQTT 5.0, if the MQTT protocol version currently used by the client is not supported, or the client specifies a wrong protocol version or protocol name. For example, suppose the client sets the protocol version to 6. In that case, the server can send a CONNACK packet with Reason Code 0x84, indicate that the protocol version is not supported and its identity as an MQTT broker, and then close the network connection.Of course, the server can also choose to close the network connection directly, because the MQTT client using MQTT 3.1 or 3.1.1 may not understand the meaning of the Reason Code 0x84. Both versions use 0x01 in the CONNACK packet to indicate that the protocol version specified by the client is not supported.
0x85 Client Identifier not valid CONNACK Only used for CONNACK packets, indicating that the Client ID is a valid string, but the server does not allow it. Possible situations are that the Clean Start is 0, but the Client ID is empty, or the Client ID exceeds the maximum length allowed by the server, and so on.
0x86 Bad User Name or Password CONNACK Only used for CONNACK packets, indicating that the client has used the wrong username or password, which means the client will be refused to connect.
0x87 Not authorized CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT When the client uses token authentication or enhanced authentication, it is more appropriate to use 0x87 to indicate that the client is not authorized to connect than 0x86.When the client performs operations such as publishing and subscribing, if the authorization check of the server is not passed, the server can also specify the Reason Code 0x87 in the response packet such as PUBACK, to indicate the authorization result.
0x88 Server unavailable CONNACK Only used in the CONNACK packets to indicate to the client that the current server is unavailable. For example, it could indicate that the authentication service of the server is experiencing issues and cannot accept new clients.
0x89 Server busy CONNACK, DISCONNECT It shows the client that the server is busy, please try again later.
0x8A Banned CONNACK Only used for CONNACK packets, indicating that the client is prohibited from logging in. For example, the server detects the abnormal connection behavior of the client, so the Client ID or IP address of the client is added to the blacklist, or the background administrator manually blocks the client. Of course, the above usually depends on the specific server implementation.
0x8B Server shutting down DISCONNECT Only used for DISCONNECT packets, and only the server can use it.If the server is or is about to shut down, it can actively send a DISCONNECT packet with Reason Code 0x8B to inform the client that the connection is terminated because the server is shutting down.This can help the client avoid continuing to initiate a connection request to the server after the connection is closed.
0x8C 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 from the previous authentication during re-authentication, the server will send a CONNACK or DISCONNECT packet with Reason Code 0x8C.
0x8D Keep Alive timeout DISCONNECT Only used for DISCONNECT packets, and only the server can use it.If the client fails to maintain communication within 1.5 times the Keep Alive time, the server will send a DISCONNECT packet with Reason Code 0x8D and close the network connection.
0x8E Session taken over DISCONNECT Only used for DISCONNECT packets, and only the server can use it.When the client connects to the server, if there is already a client connection using the same Client ID in the server, then the server will send a DISCONNECT packet with Reason Code 0x8E to the existing client, indicating that the session has been taken over by the new client. The server then closes the network connection for the current client.Regardless of whether the Clean Start in the new client connection is 0 or 1, the server will use this Reason Code to indicate to the existing client that the session has been taken over.
0x8F Topic Filter invalid SUBACK, UNSUBACK, DISCONNECT The topic filter is well-formed, but not accepted by the server. For example, the level of the topic filter exceeds the maximum limit allowed by the server, or the topic filter contains characters not accepted by the current server, such as spaces.
0x90 Topic Name invalid CONNACK, PUBACK, PUBREC, DISCONNECT The topic name is well-formed, but not accepted by the client or server.
0x91 Packet Identifier in use PUBACK, PUBREC, SUBACK, UNSUBACK This means that the Packet ID received in the packet is already in use. For example, if the sender sends a QoS 1 packet with Packet ID 100, but the receiver believes there is a QoS 2 packet using the same Packet ID that has not yet completed its message flow.This usually indicates that the current session state between the client and server is not matching, and it may be necessary to reset the session state by setting Clean Start to 1 and reconnecting.
0x92 Packet Identifier not found PUBREL, PUBCOMP Indicates that no corresponding Packet ID is found, which only occurs during the QoS 2 packet exchange process. For example, when the receiver replies with a PUBREC packet, the sender does not find a PUBLISH packet waiting for confirmation with the same Packet ID, or when the sender sends a PUBREL packet, the receiver does not find a PUBREC packet with the same Packet ID.This usually means that the current session state between the client and the server does not match, and it may be necessary to reset the session state by setting Clean Start to 1 and reconnecting.
0x93 Receive Maximum exceeded DISCONNECT Only used for DISCONNECT packets, indicating that the maximum received value has been exceeded.MQTT 5.0 adds a flow control mechanism. When connecting, the client and the server agree on the number of reliable messages they are willing to process concurrently through the Receive Maximum property (QoS > 0).So once the number of unconfirmed messages the sender sends exceeds this limit, the receiver will send a DISCONNECT packet with Reason Code 0x93 and close the network connection.
0x94 Topic Alias invalid DISCONNECT Only used for DISCONNECT packets, indicating that the subject alias is invalid.If the topic alias value in the PUBLISH packet is 0 or greater than the maximum topic alias agreed upon during the connection, the receiver will regard this as a protocol error, and it will send a DISCONNECT packet with a Reason Code of 0x94 and then close the network connection.
0x95 Packet too large CONNACK, DISCONNECT It is used to indicate that the packet exceeds the maximum allowable size. The maximum packet size allowed by the client and the server can be specified in the Maximum Packet Size attribute in the CONNECT and CONNACK packets.When one party sends a too-large packet, the other party will send a DISCONNECT packet with Reason Code 0x95, and then close the network connection.Since the client can set the will message when connecting, the CONNECT packet may also exceed the maximum message size limit that the server can handle. In this case, the server must use this Reason Code in the CONNACK packet.
0x96 Message rate too high DISCONNECT Only used for DISCONNECT packets, indicating that the maximum message publication rate allowed has been exceeded.It's important to note the difference between this Reason Code and "Quota exceeded". Message rate limits the speed of message publication, such as the maximum number of messages that can be published per second. On the other hand, Quota restricts the allocation of resources, such as the maximum number of messages a client can publish in a day. However, a client might exhaust its quota within an hour.
0x97 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 that the quota is currently exceeded through a CONNACK or SUBACK packet.Some strict clients and servers may choose to send a DISCONNECT packet and then close the connection when they find that the peer has exceeded the quota.
0x98 Administrative action DISCONNECT Only used for DISCONNECT packets, indicate to the client that the connection has been closed due to a management operation, such as an administrator kicking out the client connection in the background.
0x99 Payload format invalid CONNACK, PUBACK, PUBREC, DISCONNECT When the Payload Format Indicator property is included in the packet, the receiver can check whether the payload format in the message matches this property. If they do not match, the receiver must send an acknowledgment packet with Reason Code 0x99.Some strict clients or servers may directly send a DISCONNECT packet and then close the network connection.If there is a problem with the will message in the CONNECT packet, the server will send a CONNACK packet with Reason Code 0x99 and then close the network connection.
0x9A Retain not supported CONNACK, DISCONNECT When the server does not support retained messages, but the client sends them, the server will send it a DISCONNECT packet with Reason Code 0x9A and then close the network connection.Since the client can also set the will message as retained when connecting, the server may also use this Reason Code in the CONNACK packet.
0x9B QoS not supported CONNACK, DISCONNECT Used to indicate that the current QoS level is not supported. If the QoS specified by the client in the message (including the will message) is greater than the maximum QoS supported by the server, the server will send a DISCONNECT or CONNACK packet with Reason Code 0x9B and close the network connection.In most cases, this Reason Code is used by the server. But when the client receives a message that is not from a subscription, and the QoS of the message is greater than the maximum QoS it supports, it will also send a DISCONNECT packet with Reason Code 0x9B and then close the network connection. This situation usually means that there may be a problem with the implementation of the server.
0x9C Use another server CONNACK, DISCONNECT The server uses this Reason Code in the CONNACK or DISCONNECT packet to inform the client that it should temporarily switch to another server.If another server is not known by the client, then this Reason Code also needs to be used together with the Server Reference property to inform the client of the address of the new server.
0x9D Server moved CONNACK, DISCONNECT The server uses this Reason Code in the CONNACK or DISCONNECT packet to inform the client that it should permanently switch to another server.If another server is not known by the client, then this Reason Code also needs to be used together with the Server Reference property to inform the client of the address of the new server.
0x9E Shared Subscriptions not supported SUBACK, DISCONNECT When the server does not support shared subscription, but the client tries to establish a shared subscription, the server can send a SUBACK packet with Reason Code 0x9E to reject the subscription request, or it can directly send a DISCONNECT packet with Reason Code 0x9E and then close the network connection.
0x9F Connection rate exceeded CONNACK, DISCONNECT Used to indicate that the client has exceeded the connection rate limit. The server can limit the connection rate of the client. When the client connects too fast, the server can send a CONNACK packet with Reason Code 0x9F to reject the new connection.Of course, this is not an absolute scenario. As not all clients will wait for a while before reconnecting, some server implementations may choose to temporarily suspend the connection instead of returning a CONNACK.
0xA0 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 in a single authorization. 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 is closed because the authorized maximum connection time has been exceeded. After receiving the DISCONNECT packet containing this Reason Code, the client can re-obtain the authentication credentials and request the connection again.
0xA1 Subscription Identifiers not supported SUBACK, DISCONNECT When the server does not support the subscription identifier, but the client's subscription request contains the subscription identifier, the server can send a SUBACK packet with Reason Code 0xA1 to reject the subscription request, or directly send a DISCONNECT packet with Reason Code 0xA1 and then close the network connection.
0xA2 Wildcard Subscriptions not supported SUBACK, DISCONNECT When the server does not support wildcard subscription, but the client's subscription request contains topic wildcards, the server can send a SUBACK packet with Reason Code 0xA2 to reject the subscription request, or directly send a DISCONNECT packet with Reason Code 0xA2 and then close the network connection.
Try EMQX Cloud for Free
A fully managed MQTT service for IoT
Get Started →

Related Posts

Aug 12, 2022EMQX Team
What is the MQTT Keep Alive parameter for?

This article introduces the Keep Alive mechanism in the MQTT protocol and how to use it in EMQX. Developers can use this feature to ensure the stability of MQTT connections.

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.