MQTT Reason Code Introduction and Quick Reference
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.
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.
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 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
|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.|