Fehlerbehebung

MQTT-Verbindungsfehler: Ursachen und Lösungen

MQTT-Verbindungsfehler schnell beheben: Timeouts, ECONNREFUSED, TLS-Fehler, Mixed Content, CONNACK-Codes, MQTT-5-Reason-Codes und Client-ID-Reconnect-Schleifen.

Aktualisiert · 8 Min. Lesezeit

Eine MQTT-Verbindung kann auf vier Ebenen scheitern: im Netzwerk (DNS und TCP), beim Transport (TLS oder WebSocket), beim MQTT-Handshake (CONNECT / CONNACK) und in der laufenden Session (Keep-Alive und Disconnects). Die richtige Ebene zu finden, ist schon die halbe Lösung. Dieser Guide geht jede davon durch – mit den genauen Fehlermeldungen und Reason Codes, die dir wahrscheinlich begegnen.

Schnelle Einordnung

SymptomEbeneWahrscheinlichste Ursache
Fehler ENOTFOUND / getaddrinfoDNSTippfehler im Hostnamen oder URL-Schema im Host-Feld angegeben
Hängt, dann TimeoutNetzwerkFirewall verwirft den Port, falscher Port oder TCP-Port aus dem Browser verwendet
ECONNREFUSEDNetzwerkAuf diesem Host und Port lauscht nichts
Zertifikats- oder Handshake-FehlerTLSNicht vertrauenswürdige CA, Hostname passt nicht oder TLS gegen einen unverschlüsselten Port
Verbindung direkt nach dem Connect geschlossenMQTTCONNACK mit Fehlercode – siehe Tabellen unten
Verbindet sich, bricht dann immer wieder abSessionDoppelte Client-ID oder falsch konfigurierter Keep-Alive

Verbindungs-Timeouts

Ein Timeout bedeutet: Deine Pakete gingen raus, und nichts kam zurück. Der Broker hatte nie die Chance, Nein zu sagen. Prüfe der Reihe nach:

  1. Der Port passt zum Transport. mqtt:// auf 1883, mqtts:// auf 8883, wss:// auf dem WebSocket-Port des Brokers. Siehe MQTT-Ports erklärt.
  2. Dein Netzwerk lässt den Port zu. Firmen- und Gastnetze blockieren oft 1883 und 8883. Teste wss:// auf 443, um das zu bestätigen.
  3. Der Broker läuft. Öffentliche Sandboxes starten ohne Vorwarnung neu; teste einen anderen Broker, um dein eigenes Setup als Ursache auszuschließen.
  4. Deine Server-Firewall ist offen. Bei selbst gehosteten Brokern muss die Cloud-Security-Group eingehenden Traffic auf dem Listener-Port erlauben.

ECONNREFUSED

ECONNREFUSED ist eine schnelle, explizite Ablehnung durch das Betriebssystem: Der Host ist erreichbar, aber auf diesem Port lauscht kein Prozess. Typische Gründe sind ein Broker, der nicht läuft, ein Listener, der nur an 127.0.0.1 gebunden ist, ein Container-Port, der nie veröffentlicht wurde (docker run -p 1883:1883), oder ein Connect auf localhost aus einem Container heraus, während der Broker in einem anderen Container läuft.

TLS-Fehler

  • Selbstsignierte oder unbekannte CA (SELF_SIGNED_CERT_IN_CHAIN, UNABLE_TO_VERIFY_LEAF_SIGNATURE): Gib dem Client die CA-Datei. Deaktiviere die Prüfung nicht außerhalb lokaler Tests.
  • Hostname passt nicht (ERR_TLS_CERT_ALTNAME_INVALID): Verbinde dich über den Namen im Zertifikat, nicht über eine IP-Adresse oder einen internen Alias.
  • Wrong version number / packet length too long: Du sprichst TLS mit einem unverschlüsselten Port (zum Beispiel mqtts:// auf 1883) oder unverschlüsseltes MQTT mit einem TLS-Port.
  • Abgelaufenes Zertifikat: Prüfe die Gültigkeitsdaten mit openssl s_client -connect host:8883 -servername host.

Fehler nur im Browser: Mixed Content und WebSocket-Pfade

Browser können MQTT nur über WebSockets nutzen und bringen eigene Regeln mit. Eine über HTTPS ausgelieferte Seite kann kein ws:// öffnen – der Browser blockiert das als Mixed Content, bevor überhaupt ein Paket gesendet wird, und der Fehler taucht nur in der Entwicklerkonsole auf. Nutze wss://. Der andere häufige Fehler ist ein fehlender Pfad: Viele Broker erwarten /mqtt, und ohne ihn scheitert das WebSocket-Upgrade mit einem 404. Mehr dazu in MQTT über WebSockets.

Eine funktionierende wss-Verbindung testen

CONNACK-Return-Codes in MQTT 3.1.1

Funktionieren Netzwerk und Transport, antwortet der Broker auf CONNECT mit CONNACK. In MQTT 3.1.1 enthält es einen Return Code von einem Byte:

CodeBedeutungWas zu tun ist
0Verbindung akzeptiert (Connection accepted)Nichts – du bist verbunden
1Nicht akzeptierte Protokollversion (Unacceptable protocol version)Der Broker unterstützt die angefragte Version nicht; wechsle zwischen MQTT 3.1.1 und 5
2Kennung abgelehnt (Identifier rejected)Client-ID ist ungültig, zu lang, leer, obwohl das nicht erlaubt ist, oder gesperrt
3Server nicht verfügbar (Server unavailable)Broker ist überlastet oder in Wartung; mit Backoff erneut versuchen
4Falscher Benutzername oder falsches Passwort (Bad user name or password)Zugangsdaten und deren Kodierung prüfen
5Nicht autorisiert (Not authorized)Der Account darf sich nicht verbinden; Broker-ACLs oder die Client-ID-Regel prüfen

Häufige MQTT-5-Reason-Codes

MQTT 5 ersetzt Return Codes durch Reason Codes. Alles ab 0x80 ist ein Fehler. Dieselben Codes können im CONNACK oder in einem vom Server gesendeten DISCONNECT auftauchen:

CodeNameTypische Ursache
0x80Unspecified errorAllgemeiner Fehler; Broker-Logs prüfen
0x84Unsupported Protocol VersionBroker spricht nur 3.1.1
0x85Client Identifier not validFehlerhafte oder nicht erlaubte Client-ID
0x86Bad User Name or PasswordFalsche Zugangsdaten
0x87Not authorizedGültiger Benutzer ohne Berechtigung zum Verbinden
0x88Server unavailableBroker kann gerade keine Verbindungen annehmen
0x8ABannedClient oder IP vom Betreiber gesperrt
0x8CBad authentication methodEnhanced-Auth-Methode nicht unterstützt
0x95Packet too largeCONNECT überschreitet die maximale Paketgröße des Brokers
0x97Quota exceededAccount hat ein Verbindungs- oder Nutzungslimit erreicht
0x9FConnection rate exceededZu schnelle Reconnects; Backoff einbauen

Zwei weitere tauchen während einer Session in DISCONNECT-Paketen auf: 0x8D (Keep Alive timeout) und 0x8E (Session taken over). Beide werden unten behandelt. Den Überblick darüber, was sich mit MQTT 5 geändert hat, findest du unter MQTT 5 vs. 3.1.1.

Übernahme-Schleifen durch Client-IDs

Die Spezifikation verlangt, dass ein Broker einen bestehenden Client trennt, sobald eine neue Verbindung mit derselben Client-ID eintrifft. Teilen sich zwei Geräte – oder zwei Browser-Tabs – eine ID und verbinden sich beide automatisch neu, werfen sie sich gegenseitig alle paar Sekunden hinaus. In MQTT 5 erhält der Verlierer ein DISCONNECT mit 0x8E; in 3.1.1 wird einfach der Socket geschlossen.

Disconnects durch Keep-Alive

Der Keep-Alive-Wert im CONNECT sagt dem Broker, wie oft er Traffic erwarten kann. Sieht er für das Anderthalbfache dieses Intervalls nichts, schließt er die Verbindung. Clients senden im Leerlauf ein PINGREQ, aber eine blockierte Event-Loop, ein schlafendes Gerät oder ein aggressives Idle-Timeout in NAT oder Load Balancer kann die Verbindung trotzdem kappen. Halte das Intervall unter dem Idle-Timeout deines Netzwerks (60 Sekunden sind ein üblicher Standard) und blockiere niemals den Thread, der den MQTT-Client bedient.

Den echten Fehler loggen

Die meisten Bibliotheken verschweigen den Grund, solange du nicht darauf hörst. Mit MQTT.js:

debug.mjs
import mqtt from 'mqtt';

const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
  protocolVersion: 5,
  clientId: `debug-${Math.random().toString(16).slice(2, 10)}`,
  reconnectPeriod: 5000,
});

client.on('connect', (connack) => console.log('connected', connack.reasonCode ?? 0));
client.on('error', (err) => console.error('error:', err.message, err.code));
client.on('disconnect', (packet) => console.warn('server disconnect, reason', packet.reasonCode));
client.on('close', () => console.warn('socket closed'));

Checkliste

  1. Bestätige den Round Trip auf einem bekanntermaßen funktionierenden öffentlichen Broker im Online-Client.
  2. Gleiche Schema, Port und Pfad mit dem dokumentierten Listener des Brokers ab.
  3. Lies den CONNACK-Code oder Reason Code, statt zu raten.
  4. Nutze eine eindeutige Client-ID und verbinde dich mit Backoff neu.
  5. Halte den Keep-Alive kürzer als jedes Idle-Timeout auf der Strecke.

Ein vollständiges Testverfahren findest du unter MQTT-Broker testen.

Häufig gestellte Fragen

Was bedeutet bei MQTT „Connection refused: not authorized“?

Der Broker hat die Netzwerkverbindung angenommen, den Client aber abgelehnt. In MQTT 3.1.1 ist das CONNACK-Return-Code 5, in MQTT 5 Reason Code 0x87. Die Zugangsdaten können gültig sein, aber der Account darf sich nicht verbinden oder diese Client-ID nicht verwenden.

Warum trennt sich mein MQTT-Client ständig und verbindet sich neu?

Die häufigste Ursache sind zwei Clients mit derselben Client-ID. Der Broker trennt die ältere Session, sobald sich eine neue mit dieser ID verbindet, und wenn sich beide automatisch neu verbinden, werfen sie sich in einer Schleife gegenseitig hinaus. Gib jedem Client eine eindeutige ID.

Warum läuft meine MQTT-Verbindung in einen Timeout, statt abgelehnt zu werden?

Ein Timeout bedeutet, dass überhaupt keine Antwort kam – das deutet meist auf eine Firewall hin, die Pakete stillschweigend verwirft, auf einen falschen Host oder darauf, dass der TCP-Port aus einem Browser genutzt wird. Eine Ablehnung heißt dagegen, dass etwas geantwortet und Nein gesagt hat.