Les reason codes MQTT sont les valeurs d'état sur un octet que les brokers et clients MQTT 5 placent dans les acquittements et les paquets DISCONNECT pour indiquer précisément ce qui s'est passé. Cette référence répertorie chaque code, les paquets qui peuvent le porter, ce qui le déclenche généralement et comment y remédier, pour transformer un 0x87 ou un 0x97 énigmatique dans vos journaux en action concrète.
Comment fonctionnent les reason codes MQTT
MQTT 3.1.1 ne comptait qu'une poignée de valeurs d'état : six return codes dans le CONNACK et une seule valeur d'échec (0x80) dans le SUBACK. Tout le reste, comme une publication rejetée ou une déconnexion côté broker, était silencieux : la connexion se fermait simplement. MQTT 5 a remplacé cela par un ensemble commun de reason codes utilisé dans CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT et AUTH. C'est l'une des fonctionnalités de MQTT 5 les plus utiles pour quiconque exploite des appareils sur le terrain.
Deux règles rendent la table facile à lire :
- Les valeurs inférieures à
0x80signifient un succès ou un résultat qui n'est pas une erreur, comme « QoS 1 accordée » ou « aucun subscriber correspondant ». - Les valeurs de
0x80et plus signifient un échec. Le paquet qui porte le code indique quelle opération a échoué.
De nombreux paquets peuvent aussi porter une propriété Reason String, une explication lisible fournie par l'émetteur. Journalisez-la toujours lorsqu'elle est présente : elle contient souvent la limite exacte qui a été atteinte.
Codes de succès et d'information
| Code | Nom | Paquets | Signification |
|---|---|---|---|
| 0x00 | Success / Normal disconnection / Granted QoS 0 | CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH, DISCONNECT, SUBACK | L'opération a réussi ; dans un SUBACK, l'abonnement a été accordé en QoS 0 |
| 0x01 | Granted QoS 1 | SUBACK | Abonnement accepté avec une QoS maximum de 1 |
| 0x02 | Granted QoS 2 | SUBACK | Abonnement accepté avec une QoS maximum de 2 |
| 0x04 | Disconnect with Will Message | DISCONNECT | Le client part proprement mais demande au broker de publier son Will |
| 0x10 | No matching subscribers | PUBACK, PUBREC | Publication acceptée, mais personne n'était abonné |
| 0x11 | No subscription existed | UNSUBACK | Vous vous êtes désabonné d'un filtre auquel vous n'étiez pas abonné |
| 0x18 | Continue authentication | AUTH | L'échange d'authentification étendue se poursuit |
| 0x19 | Re-authenticate | AUTH | Le client lance une ré-authentification sur une connexion existante |
Un SUBACK qui accorde une QoS inférieure à celle demandée n'est pas une erreur. Si vous demandez la QoS 2 et obtenez 0x01, la QoS maximum du broker est 1 pour votre connexion, et les messages arriveront au plus en QoS 1.
Référence des reason codes d'erreur
| Code | Nom | Paquets | Cause habituelle | Solution |
|---|---|---|---|---|
| 0x80 | Unspecified error | Tous les acquittements, DISCONNECT | Le broker a refusé sans raison précise | Lisez la Reason String et les journaux du broker |
| 0x81 | Malformed Packet | CONNACK, DISCONNECT | Encodage invalide, UTF-8 incorrect, longueurs erronées | Mettez à jour la bibliothèque cliente ; vérifiez les encodeurs personnalisés |
| 0x82 | Protocol Error | CONNACK, DISCONNECT | Paquet valide mais envoyé dans le mauvais ordre ou avec des champs interdits | Recherchez un CONNECT en double ou un mauvais usage des propriétés |
| 0x83 | Implementation specific error | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT | Une politique propre au broker a rejeté l'opération | Consultez la documentation du broker et la Reason String |
| 0x84 | Unsupported Protocol Version | CONNACK | Le broker ne parle pas la version demandée | Utilisez MQTT 3.1.1 ou 5.0 selon ce qui est pris en charge |
| 0x85 | Client Identifier not valid | CONNACK | Client ID vide, trop long ou interdit | Utilisez un client ID valide et unique |
| 0x86 | Bad User Name or Password | CONNACK | Identifiants erronés ou mal formés | Recopiez le nom d'utilisateur et le mot de passe |
| 0x87 | Not authorized | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT | Les identifiants ou le client n'ont pas la permission | Vérifiez les identifiants, l'association du client ID et les droits sur les topics |
| 0x88 | Server unavailable | CONNACK | Le broker ne peut pas accepter de connexions pour le moment | Réessayez avec un backoff |
| 0x89 | Server busy | CONNACK, DISCONNECT | Le broker est surchargé | Réessayez plus tard avec backoff et jitter |
| 0x8A | Banned | CONNACK | Le client ou l'adresse est bloqué | Arrêtez les boucles de tentatives ; corrigez les identifiants ; contactez l'opérateur |
| 0x8B | Server shutting down | DISCONNECT | Arrêt ou redémarrage planifié | Reconnectez-vous avec un backoff |
| 0x8C | Bad authentication method | CONNACK, DISCONNECT | Méthode d'authentification étendue non prise en charge | Supprimez ou corrigez l'Authentication Method |
| 0x8D | Keep Alive timeout | DISCONNECT | Aucun paquet reçu en 1,5 x keep alive | Faites tourner la boucle réseau ; vérifiez la connectivité |
| 0x8E | Session taken over | DISCONNECT | Un autre client s'est connecté avec le même client ID | Donnez à chaque client un ID unique |
| 0x8F | Topic Filter invalid | SUBACK, UNSUBACK, DISCONNECT | Filtre mal formé, par exemple a/#/b |
Corrigez la position des wildcards |
| 0x90 | Topic Name invalid | CONNACK, PUBACK, PUBREC, DISCONNECT | Wildcards ou caractères invalides dans un topic de publication | Publiez sur un nom de topic concret |
| 0x91 | Packet Identifier in use | PUBACK, PUBREC, SUBACK, UNSUBACK | Packet ID réutilisé alors qu'il est encore en vol | Bug de bibliothèque ou gestion personnalisée des packet ID |
| 0x92 | Packet Identifier not found | PUBREL, PUBCOMP | État QoS 2 perdu, souvent après une réinitialisation de session | Vérifiez les paramètres de persistance de session |
| 0x93 | Receive Maximum exceeded | DISCONNECT | Trop de publications QoS 1/2 non acquittées | Respectez le Receive Maximum du pair |
| 0x94 | Topic Alias invalid | DISCONNECT | Alias hors limites ou non défini | Réinitialisez les aliases à la reconnexion ; respectez le maximum |
| 0x95 | Packet too large | CONNACK, DISCONNECT | Le paquet dépasse le Maximum Packet Size | Réduisez ou découpez les payloads |
| 0x96 | Message rate too high | DISCONNECT | Publication plus rapide que permis | Limitez le rythme des publications |
| 0x97 | Quota exceeded | CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT | Une limite d'offre ou de compte a été atteinte | Réduisez l'usage ou passez à une offre supérieure |
| 0x98 | Administrative action | DISCONNECT | Un opérateur a déconnecté le client | Renseignez-vous auprès de l'administrateur du broker |
| 0x99 | Payload format invalid | CONNACK, PUBACK, PUBREC, DISCONNECT | Le Payload Format Indicator annonce de l'UTF-8 mais les octets n'en sont pas | Corrigez l'encodage ou retirez l'indicateur |
| 0x9A | Retain not supported | CONNACK, DISCONNECT | Flag retain utilisé là où il n'est pas autorisé | Publiez sans retain |
| 0x9B | QoS not supported | CONNACK, DISCONNECT | QoS de publication supérieure au maximum du broker | Baissez la QoS au maximum annoncé |
| 0x9C | Use another server | CONNACK, DISCONNECT | Le broker redirige temporairement le client | Suivez la propriété Server Reference |
| 0x9D | Server moved | CONNACK, DISCONNECT | Le broker redirige définitivement | Mettez à jour l'hôte configuré |
| 0x9E | Shared Subscriptions not supported | SUBACK, DISCONNECT | Filtre $share/... non autorisé |
Utilisez une offre ou un broker avec shared subscriptions |
| 0x9F | Connection rate exceeded | CONNACK | Trop de tentatives de connexion | Ajoutez un backoff à la logique de reconnexion |
| 0xA0 | Maximum connect time | DISCONNECT | Durée de vie maximale de la connexion atteinte | Reconnectez-vous ; attendez-vous à des déconnexions périodiques |
| 0xA1 | Subscription Identifiers not supported | SUBACK, DISCONNECT | Propriété Subscription Identifier non autorisée | Supprimez la propriété |
| 0xA2 | Wildcard Subscriptions not supported | SUBACK, DISCONNECT | Wildcards non autorisés pour ce client | Abonnez-vous à des topics explicites |
Notez que certains codes, comme 0x8D et 0x8E, n'apparaissent que dans un DISCONNECT envoyé par le broker. D'autres, comme 0x84 à 0x88, ne peuvent apparaître que dans un CONNACK, car ils décrivent pourquoi la connexion a été refusée d'emblée.
Correspondance entre return codes MQTT 3.1.1 et MQTT 5
Si vous prenez en charge les deux versions du protocole, cette correspondance garde votre gestion d'erreurs cohérente. L'explication détaillée se trouve dans le guide des return codes CONNACK MQTT.
| CONNACK MQTT 3.1.1 | Équivalent MQTT 5 |
|---|---|
| 0 Connection accepted | 0x00 Success |
| 1 Unacceptable protocol version | 0x84 Unsupported Protocol Version |
| 2 Identifier rejected | 0x85 Client Identifier not valid |
| 3 Server unavailable | 0x88 Server unavailable |
| 4 Bad user name or password | 0x86 Bad User Name or Password |
| 5 Not authorized | 0x87 Not authorized |
Journaliser les reason codes MQTT en Python
Avec paho-mqtt 2.x et CallbackAPIVersion.VERSION2, chaque callback reçoit un objet ReasonCode. Sa forme textuelle est le nom défini par la spécification et .value est le code numérique, exactement ce qu'il vous faut dans les journaux :
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
print(f"CONNACK: {reason_code} (0x{reason_code.value:02X})")
if reason_code.is_failure:
return
client.subscribe("connectmq/demo/b7d2/#", qos=2)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
for rc in reason_code_list:
print(f"SUBACK: {rc} (0x{rc.value:02X})")
def on_disconnect(client, userdata, flags, reason_code, properties):
reason = getattr(properties, "ReasonString", None) if properties else None
print(f"DISCONNECT: {reason_code} (0x{reason_code.value:02X}) {reason or ''}")
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id="reason-demo-b7d2",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_disconnect = on_disconnect
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_forever()
Exécutez-le contre le serveur MQTT public gratuit, réservé aux tests et jamais aux données de production, et vous verrez Success à la connexion et une QoS accordée dans le SUBACK. Essayez de vous abonner à un filtre invalide comme connectmq/demo/b7d2/#/x pour voir 0x8F Topic Filter invalid en action. Avec MQTT.js, les mêmes informations se trouvent dans connack.reasonCode, dans le tableau granted du callback d'abonnement et dans le paquet de l'événement disconnect.
Méthode de débogage par reason code
Un ordre pratique pour analyser un échec :
- Identifiez le paquet. Un code dans un CONNACK signale un problème de connexion ; dans un SUBACK, un problème d'abonnement ; dans un DISCONNECT, un problème en cours d'exécution.
- Lisez la Reason String. Elle ramène généralement la cause à une limite ou une règle précise.
- Vérifiez d'abord les identifiants et l'identité pour
0x85,0x86et0x87. Le guide pour corriger l'erreur MQTT connection refused: not authorized traite ce sujet en profondeur. - Vérifiez les limites pour
0x93,0x95,0x96et0x97: taille des messages, débit, nombre de connexions et messages en vol. - Vérifiez l'hygiène de la flotte pour
0x8E: les client ID en double sont la cause la plus fréquente des boucles de déconnexion.
Les reason codes sur ConnectMQ
ConnectMQ prend en charge MQTT 3.1.1 et 5.0 : les clients MQTT 5 reçoivent donc les reason codes ci-dessus. Les quotas des offres se manifestent sous la forme 0x97 Quota exceeded, par exemple lorsqu'un broker Serverless (Free) a déjà atteint son maximum de 25 connexions. Les fonctionnalités de l'offre comptent aussi : l'offre gratuite accorde la QoS jusqu'à 1, si bien qu'un abonnement en QoS 2 est accordé à une QoS inférieure dans le SUBACK, tandis que la QoS 2 et les shared subscriptions sont incluses dans l'offre Serverless (Paid). Les échecs de connexion répétés sont considérés comme suspects et l'IP source peut être bloquée : ne laissez donc jamais un client réessayer de mauvais identifiants en boucle serrée.
Pour comprendre ce que fait un broker MQTT de ces codes, ou voir le protocole complet dans son contexte, consultez le tutoriel MQTT.
Déboguer plus vite avec ConnectMQ
Un broker MQTT managé doté d'un client intégré au navigateur et d'un explorateur de topics en direct permet de reproduire beaucoup plus vite une publication ou un abonnement en échec. Créez un broker Serverless (Free) sur app.connectmq.com, sans carte bancaire, et testez votre gestion d'erreurs face à de vraies réponses MQTT 5.
Questions fréquentes
Quelle est la différence entre un reason code et un return code ?
Return code est le terme MQTT 3.1.1 désignant les six valeurs du CONNACK. MQTT 5 a généralisé l'idée sous la forme de reason codes présents dans presque tous les acquittements et dans le DISCONNECT.
Quels reason codes signifient un succès ?
Toute valeur inférieure à 0x80. Cela comprend 0x00 Success, 0x01 et 0x02 pour la QoS accordée, ainsi que des valeurs informatives comme 0x10 No matching subscribers.
Que signifie le reason code MQTT 0x97 ?
0x97 correspond à Quota exceeded : le client a atteint une limite, comme le nombre maximum de connexions ou une restriction de l'offre. Réduisez l'usage ou passez à une offre aux limites plus élevées.
Les clients MQTT 3.1.1 reçoivent-ils les reason codes MQTT 5 ?
Non. Une connexion 3.1.1 ne reçoit que les return codes CONNACK classiques et la valeur d'échec 0x80 du SUBACK. Connectez-vous avec la version 5 du protocole pour recevoir des reason codes détaillés.



