Certain codes are only sent via certain commands - for example, SUBACK cannot send a 0x01, 0x02 or 0x09 status. The status codes for CONNACK are all compatible with MQTT 3.1. I have attempted to clarify each of the status codes, so none are ambiguous. 0x04 has been changed from "bad username or password" to "bad payload" which for CONNACK means the same thing, but for other commands has slightly different meaning.
Enumeration HEX Meaning
0 0x0 Accepted
1 0x1 (CONNACK) Refused: unacceptable protocol version
The protocol version specified in the header is incompatible with the server's
protocol.
2 0x2 (CONNACK) Refused: identifier rejected
The idenitifer specified in the connection header does not fit the required
format, or already exists on the server.
3 0x3 (CONNACK, SUBACK, UNSUBACK, PUBACK, PUBREL) Refused: server unavailable
The server has gone down, the client should disconnect any active connections
and retry at a later time. If the server is attempting to rate limit connections,
it should use 0x06 instead. Similar to a HTTP 503 error.
4 0x4 (CONNACK, SUBACK, UNSUBACK, PUBACK, PUBREL) Refused: bad payload
The request was invalid. If coming from a CONNACK the username or password
specified is malformed or missing. This MAY indicate that the server considers
a username and or password mandatory for connection. If the username and
password are both specified, but are not registered on the server, a 0x05 should
be sent instead. If coming from a SUBACK, UNSUBACK, PUBACK, PUBREL, this MAY
indicate the topic or message are missing, or malformed and unreadable. Similar
to an HTTP 400 error.
5 0x5 (CONNACK, SUBACK, UNSUBACK, PUBACK, PUBREL) Refused: not authorized
The username or password specified does not have sufficient priveleges to
perform this action. In the case of PUBACK, PUBREL/suback the topic requires
specialised authorisation to be published/subscribed to. If the username and
password are missing, or in some way malformed and unreadable - a 0x04 should be
sent instead. Similar to an HTTP 403 error.
6 0x6 (CONNACK, SUBACK, PUBACK, PUBREL) Refused: at limit
If coming from a CONNACK, the server is at capacity and is not accepting any
more client connections. If from a SUBACK or PUBACK, PUBREL, the topic is at
capacity (already has too many subscribers, or too many publishers publishing
at once). The client MAY wait and try again at a later time. This MAY also be
used by servers to implement rate limiting - stopping clients from sending too
many requests in a given time period. Similar to an HTTP 429 error.
7 0x7 (SUBACK, UNSUBACK, PUBACK, PUBREL) Refused: Topic not registered
The server has a fixed list of registered topics, and the topic provided is not
in that list. Similar to an HTTP 404 error.
8 0x8 (SUBACK, UNSUBACK, PUBACK, PUBREL) Refused: Bad topic
The server is refusing the topic based on its own validation criteria. This MAY
be due to the length of the topic (while the spec indicates that topics can be
between 1b-64kb, the server MAY have stricter criteria), it MAY mean the number
of levels in the topic is too many for the server to handle, or the wildcard
combination means the topic is too general and will overload the server if
utilised. If the topic does not conform to the spec, a 0x04 should be sent
instead, but if the server has specific topic criteria, then this is used. This
is perhaps similar to an HTTP 413 or 414 error.
9 0x9 (PUBACK, PUBREL) Refused: Bad message
The server is refusing the message based on its own validation criteria. This
MAY be due to the length of the message (while the spec indicates messages up
to 256MB can be sent, the server MAY have stricter criteria). Alternatively it
MAY mean the server cannot read the format the message is in. If the message
does not conform to the specifications then a 0x04 should be sent, but if the
message doesn't conform to the servers own criteria, then this is used. This is
perhaps similar to an HTTP 413 or 415 error.
10 (0xA) - 15 (0xF) Reserved for future use
This proposal would keep the spec as compatible as possible, while giving all ACKS a response code. Existing response codes are maintained. A key summary of changes to the 3.1 spec are:
- 3.1 explicitly specifies that PUBACK, PUBREC and UNSUBACK have no playloads. This would change that, they'd have a 1 byte payload. This could potentially break clients if they expect these commands to not have a payload.
- 3.1 states that CONNACK Payload has 1 byte for the response code, this would change to be 4 reserved bits, and 4 bits for payload - but bits 4-7 are effectively unused in 3.1, so the actual response codes would change - byte for byte.
- 3.1 specifies SUBACK's Payload bits 4-7 as reserved. These would be changed to the response code, which could potentially break clients if they were reading the whole byte as a single integer for the granted QoS
- Existing clients that are 3.1 compliant would behave as though SUBACK, UNSUBACK, PUBACK and PUBREL are all successful responses to their counterpart messages. This would not be true for all cases, and some codes indicate permanent failures about the message, meaning subsequent retries are wasted bandwidth.