MQTT Reason Codes sind Statuswerte von einem Byte, die MQTT-5-Broker und -Clients in Bestätigungen und DISCONNECT-Pakete schreiben, um genau mitzuteilen, was passiert ist. Diese Referenz listet jeden Code auf, nennt die Pakete, die ihn tragen können, was ihn typischerweise auslöst und wie Sie das Problem beheben. So wird aus einem kryptischen 0x87 oder 0x97 in Ihren Logs ein konkreter nächster Schritt.
Wie MQTT Reason Codes funktionieren
MQTT 3.1.1 kannte nur eine Handvoll Statuswerte: sechs CONNACK-Rückgabecodes und einen einzigen Fehlerwert (0x80) im SUBACK. Alles andere, etwa ein abgelehntes Publish oder eine vom Broker ausgehende Trennung, geschah stillschweigend; die Verbindung wurde einfach geschlossen. MQTT 5 ersetzte das durch einen gemeinsamen Satz von Reason Codes, die in CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT und AUTH verwendet werden. Für alle, die Geräte im Feld betreiben, etwa Edge-Gateways an SPS in mehreren Werken, ist das eine der praktischsten Funktionen von MQTT 5.
Zwei Regeln machen die Tabelle leicht lesbar:
- Werte unter
0x80bedeuten Erfolg oder ein Ergebnis ohne Fehler, etwa „granted QoS 1“ oder „no matching subscribers“. - Werte ab
0x80bedeuten einen Fehler. Das Paket, das den Code trägt, zeigt Ihnen, welche Operation fehlgeschlagen ist.
Viele Pakete können zusätzlich eine Reason-String-Property enthalten, eine für Menschen lesbare Erklärung des Senders. Protokollieren Sie diese immer, wenn sie vorhanden ist; oft nennt sie genau das Limit, das erreicht wurde.
Erfolgs- und Informationscodes
| Code | Name | Pakete | Bedeutung |
|---|---|---|---|
| 0x00 | Success / Normal disconnection / Granted QoS 0 | CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH, DISCONNECT, SUBACK | Operation erfolgreich; im SUBACK bedeutet er, dass die Subscription mit QoS 0 gewährt wurde |
| 0x01 | Granted QoS 1 | SUBACK | Subscription mit maximalem QoS 1 akzeptiert |
| 0x02 | Granted QoS 2 | SUBACK | Subscription mit maximalem QoS 2 akzeptiert |
| 0x04 | Disconnect with Will Message | DISCONNECT | Client trennt sich sauber, bittet den Broker aber, seinen Will zu veröffentlichen |
| 0x10 | No matching subscribers | PUBACK, PUBREC | Publish akzeptiert, aber niemand hatte abonniert |
| 0x11 | No subscription existed | UNSUBACK | Sie haben einen Filter abbestellt, den Sie nicht abonniert hatten |
| 0x18 | Continue authentication | AUTH | Der Austausch bei der erweiterten Authentifizierung geht weiter |
| 0x19 | Re-authenticate | AUTH | Client startet eine erneute Authentifizierung auf einer bestehenden Verbindung |
Ein SUBACK, das einen niedrigeren QoS als angefordert gewährt, ist kein Fehler. Fordern Sie QoS 2 an und erhalten 0x01, liegt das Maximum QoS des Brokers für Ihre Verbindung bei 1, und Nachrichten kommen höchstens mit QoS 1 an.
Referenz der Fehler-Reason-Codes
| Code | Name | Pakete | Typische Ursache | Lösung |
|---|---|---|---|---|
| 0x80 | Unspecified error | Alle Bestätigungen, DISCONNECT | Broker hat ohne konkreten Grund abgelehnt | Reason String und Broker-Logs lesen |
| 0x81 | Malformed Packet | CONNACK, DISCONNECT | Ungültige Kodierung, fehlerhaftes UTF-8, falsche Längen | Client-Bibliothek aktualisieren; eigene Encoder prüfen |
| 0x82 | Protocol Error | CONNACK, DISCONNECT | Paket gültig, aber in falscher Reihenfolge oder mit unzulässigen Feldern gesendet | Auf doppeltes CONNECT oder falsch genutzte Properties prüfen |
| 0x83 | Implementation specific error | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT | Broker-spezifische Richtlinie hat die Operation abgelehnt | Broker-Dokumentation und Reason String prüfen |
| 0x84 | Unsupported Protocol Version | CONNACK | Broker beherrscht die angeforderte Version nicht | MQTT 3.1.1 oder 5.0 gemäß Unterstützung verwenden |
| 0x85 | Client Identifier not valid | CONNACK | Leere, zu lange oder unzulässige Client ID | Gültige, eindeutige Client ID verwenden |
| 0x86 | Bad User Name or Password | CONNACK | Falsche oder fehlerhafte Zugangsdaten | Benutzername und Passwort neu kopieren |
| 0x87 | Not authorized | CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT | Zugangsdaten oder Client fehlt die Berechtigung | Zugangsdaten, Bindung an die Client ID und Topic-Rechte prüfen |
| 0x88 | Server unavailable | CONNACK | Broker kann derzeit keine Verbindungen annehmen | Mit Backoff erneut versuchen |
| 0x89 | Server busy | CONNACK, DISCONNECT | Broker ist überlastet | Später mit Backoff und Jitter erneut versuchen |
| 0x8A | Banned | CONNACK | Client oder Adresse ist gesperrt | Retry-Schleifen stoppen; Zugangsdaten korrigieren; Betreiber kontaktieren |
| 0x8B | Server shutting down | DISCONNECT | Geplantes Herunterfahren oder Neustart | Mit Backoff neu verbinden |
| 0x8C | Bad authentication method | CONNACK, DISCONNECT | Methode der erweiterten Authentifizierung nicht unterstützt | Authentication Method entfernen oder korrigieren |
| 0x8D | Keep Alive timeout | DISCONNECT | Innerhalb von 1,5 x Keep Alive kein Paket empfangen | Netzwerkschleife bedienen; Konnektivität prüfen |
| 0x8E | Session taken over | DISCONNECT | Ein anderer Client hat sich mit derselben Client ID verbunden | Jedem Client eine eindeutige ID geben |
| 0x8F | Topic Filter invalid | SUBACK, UNSUBACK, DISCONNECT | Fehlerhafter Filter, z. B. a/#/b |
Platzierung der Wildcards korrigieren |
| 0x90 | Topic Name invalid | CONNACK, PUBACK, PUBREC, DISCONNECT | Wildcards oder ungültige Zeichen in einem Publish-Topic | Auf einen konkreten Topic-Namen veröffentlichen |
| 0x91 | Packet Identifier in use | PUBACK, PUBREC, SUBACK, UNSUBACK | Packet ID wiederverwendet, während sie noch unterwegs war | Bibliotheksfehler oder eigene Verwaltung der Packet IDs |
| 0x92 | Packet Identifier not found | PUBREL, PUBCOMP | QoS-2-Zustand verloren, oft nach einem Session-Reset | Einstellungen zur Session-Persistenz prüfen |
| 0x93 | Receive Maximum exceeded | DISCONNECT | Zu viele unbestätigte QoS-1/2-Publishes | Receive Maximum der Gegenseite einhalten |
| 0x94 | Topic Alias invalid | DISCONNECT | Alias außerhalb des Bereichs oder undefiniert | Aliases beim Reconnect zurücksetzen; Maximum einhalten |
| 0x95 | Packet too large | CONNACK, DISCONNECT | Paket überschreitet die Maximum Packet Size | Payloads verkleinern oder aufteilen |
| 0x96 | Message rate too high | DISCONNECT | Schnelleres Veröffentlichen als erlaubt | Publishes drosseln |
| 0x97 | Quota exceeded | CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT | Ein Plan- oder Kontolimit wurde erreicht | Nutzung reduzieren oder Plan upgraden |
| 0x98 | Administrative action | DISCONNECT | Ein Betreiber hat den Client getrennt | Beim Broker-Administrator nachfragen |
| 0x99 | Payload format invalid | CONNACK, PUBACK, PUBREC, DISCONNECT | Payload Format Indicator meldet UTF-8, die Bytes sind es aber nicht | Kodierung korrigieren oder Indicator entfernen |
| 0x9A | Retain not supported | CONNACK, DISCONNECT | Retain-Flag verwendet, wo es nicht erlaubt ist | Ohne Retain veröffentlichen |
| 0x9B | QoS not supported | CONNACK, DISCONNECT | Publish-QoS über dem Maximum des Brokers | QoS auf das angekündigte Maximum senken |
| 0x9C | Use another server | CONNACK, DISCONNECT | Broker leitet den Client vorübergehend um | Der Property Server Reference folgen |
| 0x9D | Server moved | CONNACK, DISCONNECT | Broker leitet dauerhaft um | Konfigurierten Host aktualisieren |
| 0x9E | Shared Subscriptions not supported | SUBACK, DISCONNECT | Filter $share/... nicht erlaubt |
Plan oder Broker mit Shared Subscriptions verwenden |
| 0x9F | Connection rate exceeded | CONNACK | Zu viele Verbindungsversuche | Backoff in die Reconnect-Logik einbauen |
| 0xA0 | Maximum connect time | DISCONNECT | Limit für die Verbindungsdauer erreicht | Neu verbinden; mit periodischen Trennungen rechnen |
| 0xA1 | Subscription Identifiers not supported | SUBACK, DISCONNECT | Property Subscription Identifier nicht erlaubt | Property entfernen |
| 0xA2 | Wildcard Subscriptions not supported | SUBACK, DISCONNECT | Wildcards für diesen Client nicht erlaubt | Explizite Topics abonnieren |
Beachten Sie, dass einige Codes wie 0x8D und 0x8E nur in einem vom Broker gesendeten DISCONNECT auftreten. Andere, etwa 0x84 bis 0x88, können nur im CONNACK erscheinen, weil sie beschreiben, warum die Verbindung überhaupt abgelehnt wurde.
Zuordnung der MQTT-3.1.1-Rückgabecodes zu MQTT 5
Wenn Sie beide Protokollversionen unterstützen, hält diese Zuordnung Ihre Fehlerbehandlung konsistent. Die ausführliche Erklärung finden Sie im Leitfaden zu den MQTT-CONNACK-Rückgabecodes.
| MQTT 3.1.1 CONNACK | Entsprechung in 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 |
MQTT Reason Codes in Python protokollieren
Mit paho-mqtt 2.x und CallbackAPIVersion.VERSION2 erhält jeder Callback ein ReasonCode-Objekt. Seine String-Form ist der Name aus der Spezifikation, und .value ist der numerische Code, also genau das, was Sie in Logs brauchen:
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()
Führen Sie das Skript gegen den öffentlichen MQTT-Broker aus, der für solche Tests gedacht ist, und Sie sehen beim Verbinden Success und im SUBACK einen gewährten QoS. Abonnieren Sie testweise einen ungültigen Filter wie connectmq/demo/b7d2/#/x, um 0x8F Topic Filter invalid in Aktion zu sehen. Bei MQTT.js finden Sie dieselben Informationen in connack.reasonCode, im Array granted des Subscribe-Callbacks und im Paket des disconnect-Events.
Debugging-Ablauf nach Reason Code
Eine praxistaugliche Reihenfolge für die Untersuchung eines Fehlers:
- Paket identifizieren. Ein Code im CONNACK ist ein Verbindungsproblem, im SUBACK ein Subscription-Problem, im DISCONNECT ein Laufzeitproblem.
- Reason String lesen. Er grenzt die Ursache meist auf ein bestimmtes Limit oder eine Regel ein.
- Bei
0x85,0x86und0x87zuerst Zugangsdaten und Identität prüfen. Der Leitfaden zur Behebung von MQTT connection refused: not authorized behandelt das ausführlich. - Bei
0x93,0x95,0x96und0x97Limits prüfen: Nachrichtengröße, Rate, Anzahl der Verbindungen und Nachrichten in Übertragung. - Bei
0x8Edie Ordnung in der Flotte prüfen: Doppelte Client IDs sind die häufigste Ursache für Trennungsschleifen.
Tipp für verteilte Anlagen: Lassen Sie Edge-Gateways Reason Code und Reason String zusätzlich auf ein Diagnose-Topic publizieren, das der ISA-95-Struktur Ihres Unified Namespace (UNS) folgt, etwa acme/werk-stuttgart/montage/linie-1/gateway-1/diagnose. So sieht die Instandhaltung zentral, an welcher Linie Verbindungen oder Subscriptions scheitern.
Reason Codes bei ConnectMQ
ConnectMQ unterstützt MQTT 3.1.1 und 5.0, MQTT-5-Clients erhalten also die oben genannten Reason Codes. Plan-Kontingente zeigen sich als 0x97 Quota exceeded, zum Beispiel wenn ein kostenloser Serverless-Broker bereits sein Maximum von 25 Verbindungen erreicht hat. Auch die Plan-Funktionen spielen eine Rolle: Der kostenlose Plan gewährt QoS bis 1, eine QoS-2-Subscription wird im SUBACK also mit einem niedrigeren QoS gewährt, während QoS 2 und Shared Subscriptions mit dem kostenpflichtigen Serverless-Plan verfügbar sind. Wiederholte fehlgeschlagene Anmeldungen gelten als verdächtig, und die Quell-IP kann gesperrt werden. Lassen Sie einen Client daher nie in einer engen Schleife mit falschen Zugangsdaten neu verbinden.
Hintergründe dazu, was ein MQTT-Broker mit diesen Codes macht, und das vollständige Protokoll im Zusammenhang finden Sie im MQTT-Tutorial.
Schneller debuggen mit ConnectMQ
Ein verwalteter MQTT-Broker mit browserbasiertem Client und Live-Topic-Explorer macht es deutlich einfacher, ein fehlschlagendes Publish oder eine fehlschlagende Subscription zu reproduzieren. Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ganz ohne Kreditkarte, und testen Sie Ihre Fehlerbehandlung gegen echte MQTT-5-Antworten.
Häufig gestellte Fragen
Was ist der Unterschied zwischen einem Reason Code und einem Return Code?
Return Code ist der Begriff aus MQTT 3.1.1 für die sechs CONNACK-Werte. MQTT 5 hat die Idee zu Reason Codes verallgemeinert, die in fast jeder Bestätigung und im DISCONNECT vorkommen.
Welche Reason Codes bedeuten Erfolg?
Jeder Wert unter 0x80. Dazu gehören 0x00 Success, 0x01 und 0x02 für den gewährten QoS sowie Informationswerte wie 0x10 No matching subscribers.
Was bedeutet der MQTT Reason Code 0x97?
0x97 steht für Quota exceeded: Der Client hat ein Limit erreicht, etwa die maximale Anzahl an Verbindungen oder eine Plan-Beschränkung. Reduzieren Sie die Nutzung oder wechseln Sie in einen Plan mit höheren Limits.
Erhalten MQTT-3.1.1-Clients die Reason Codes von MQTT 5?
Nein. Eine 3.1.1-Verbindung erhält nur die klassischen CONNACK-Rückgabecodes und den SUBACK-Fehlerwert 0x80. Verbinden Sie sich mit Protokollversion 5, um detaillierte Reason Codes zu erhalten.



