Dépannage

Erreurs de connexion MQTT : causes et solutions

Corrigez vite les erreurs de connexion MQTT : timeouts, ECONNREFUSED, échecs TLS, contenu mixte, codes CONNACK, reason codes MQTT 5 et boucles de reconnexion.

Mis à jour · 8 min de lecture

Une connexion MQTT peut échouer à quatre niveaux : le réseau (DNS et TCP), le transport (TLS ou WebSocket), le handshake MQTT (CONNECT / CONNACK) et la session active (keep-alive et déconnexions). Identifier le niveau, c’est déjà la moitié de la solution. Ce guide les passe en revue un par un, avec les messages d’erreur et les reason codes exacts que vous risquez de rencontrer.

Diagnostic rapide

SymptômeNiveauCause la plus probable
Erreur ENOTFOUND / getaddrinfoDNSFaute de frappe dans le nom d’hôte, ou schéma d’URL inclus dans le champ hôte
Bloque, puis expireRéseauPare-feu qui bloque le port, mauvais port, ou port TCP utilisé depuis un navigateur
ECONNREFUSEDRéseauRien n’écoute sur cet hôte et ce port
Erreur de certificat ou de handshakeTLSCA non reconnue, nom d’hôte non concordant, ou TLS vers un port en clair
Connexion fermée juste après la connexionMQTTCONNACK avec un code d’erreur — voir les tableaux ci-dessous
Se connecte, puis décroche à répétitionSessionClient ID en double ou keep-alive mal configuré

Timeouts de connexion

Un timeout signifie que vos paquets sont partis et que rien n’est revenu. Le broker n’a même pas eu l’occasion de dire non. Vérifiez, dans l’ordre :

  1. Le port correspond au transport. mqtt:// sur 1883, mqtts:// sur 8883, wss:// sur le port WebSocket du broker. Voir les ports MQTT expliqués.
  2. Votre réseau autorise le port. Les réseaux d’entreprise et invités bloquent souvent 1883 et 8883. Essayez wss:// sur 443 pour le confirmer.
  3. Le broker est en ligne. Les bacs à sable publics redémarrent sans préavis ; testez un autre broker pour écarter votre propre configuration.
  4. Le pare-feu de votre serveur est ouvert. Pour les brokers auto-hébergés, le security group du cloud doit autoriser le trafic entrant sur le port du listener.

ECONNREFUSED

ECONNREFUSED est un rejet rapide et explicite du système d’exploitation : l’hôte est joignable, mais aucun processus n’écoute sur ce port. Les raisons typiques : un broker qui ne tourne pas, un listener lié uniquement à 127.0.0.1, un port de conteneur jamais publié (docker run -p 1883:1883), ou une connexion à localhost depuis un conteneur alors que le broker tourne dans un autre.

Erreurs TLS

  • CA auto-signée ou inconnue (SELF_SIGNED_CERT_IN_CHAIN, UNABLE_TO_VERIFY_LEAF_SIGNATURE) : fournissez le fichier de la CA au client. Ne désactivez pas la vérification en dehors des tests locaux.
  • Nom d’hôte non concordant (ERR_TLS_CERT_ALTNAME_INVALID) : connectez-vous avec le nom figurant sur le certificat, pas avec une adresse IP ou un alias interne.
  • Wrong version number / packet length too long : vous parlez TLS à un port en clair (par exemple mqtts:// sur 1883) ou MQTT en clair à un port TLS.
  • Certificat expiré : vérifiez les dates avec openssl s_client -connect host:8883 -servername host.

Erreurs propres au navigateur : contenu mixte et chemins WebSocket

Les navigateurs ne peuvent utiliser MQTT que sur WebSockets, et ils ajoutent leurs propres règles. Une page servie en HTTPS ne peut pas ouvrir de ws:// — le navigateur le bloque comme contenu mixte avant l’envoi du moindre paquet, et l’erreur n’apparaît que dans la console développeur. Utilisez wss://. L’autre erreur fréquente est un chemin manquant : beaucoup de brokers attendent /mqtt, et sans lui l’upgrade WebSocket échoue avec une 404. Pour en savoir plus, voir MQTT sur WebSockets.

Tester une connexion wss qui fonctionne

Codes de retour CONNACK en MQTT 3.1.1

Si le réseau et le transport fonctionnent, le broker répond au CONNECT par un CONNACK. En MQTT 3.1.1, celui-ci contient un code de retour sur un octet :

CodeSignificationQue corriger
0Connexion acceptéeRien — vous êtes connecté
1Version de protocole inacceptableLe broker ne prend pas en charge la version demandée ; basculez entre MQTT 3.1.1 et 5
2Identifiant rejetéLe client ID est invalide, trop long, vide alors que ce n’est pas autorisé, ou bloqué
3Serveur indisponibleLe broker est surchargé ou en maintenance ; réessayez avec un backoff
4Nom d’utilisateur ou mot de passe incorrectVérifiez les identifiants et leur encodage
5Non autoriséLe compte n’a pas le droit de se connecter ; vérifiez les ACL du broker ou la règle sur le client ID

Reason codes MQTT 5 courants

MQTT 5 remplace les codes de retour par des reason codes. Tout code supérieur ou égal à 0x80 est un échec. Les mêmes codes peuvent apparaître dans un CONNACK ou dans un DISCONNECT envoyé par le serveur :

CodeNomCause typique
0x80Unspecified errorÉchec générique ; consultez les logs du broker
0x84Unsupported Protocol VersionLe broker ne parle que la 3.1.1
0x85Client Identifier not validClient ID mal formé ou non autorisé
0x86Bad User Name or PasswordIdentifiants incorrects
0x87Not authorizedUtilisateur valide sans permission de se connecter
0x88Server unavailableLe broker ne peut pas accepter de connexions pour le moment
0x8ABannedClient ou IP bloqué par l’opérateur
0x8CBad authentication methodMéthode d’authentification étendue non prise en charge
0x95Packet too largeLe CONNECT dépasse la taille maximale de paquet du broker
0x97Quota exceededLe compte a atteint une limite de connexions ou d’utilisation
0x9FConnection rate exceededReconnexions trop rapides ; ajoutez un backoff

Deux autres apparaissent dans les paquets DISCONNECT pendant une session : 0x8D (Keep Alive timeout) et 0x8E (Session taken over). Tous deux sont traités ci-dessous. Pour une vue d’ensemble de ce que MQTT 5 a changé, voir MQTT 5 vs 3.1.1.

Boucles de prise de contrôle du client ID

La spécification impose au broker de déconnecter un client existant lorsqu’une nouvelle connexion arrive avec le même client ID. Si deux appareils — ou deux onglets de navigateur — partagent un ID et se reconnectent tous deux automatiquement, ils s’éjectent à tour de rôle toutes les quelques secondes. En MQTT 5, le perdant reçoit un DISCONNECT avec 0x8E ; en 3.1.1, le socket se ferme simplement.

Déconnexions liées au keep-alive

La valeur de keep-alive du CONNECT indique au broker à quelle fréquence attendre du trafic. S’il ne voit rien pendant une fois et demie cet intervalle, il ferme la connexion. Les clients envoient un PINGREQ lorsqu’ils sont inactifs, mais une boucle d’événements bloquée, un appareil en veille ou un délai d’inactivité agressif d’un NAT ou d’un load balancer peuvent quand même rompre la connexion. Gardez l’intervalle sous le délai d’inactivité de votre réseau (60 secondes est une valeur par défaut courante) et ne bloquez jamais le thread qui fait tourner le client MQTT.

Journalisez la vraie erreur

La plupart des bibliothèques masquent la raison si vous ne l’écoutez pas explicitement. Avec 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'));

Checklist

  1. Confirmez l’aller-retour sur un broker public fiable dans le client en ligne.
  2. Faites correspondre schéma, port et chemin au listener documenté du broker.
  3. Lisez le code CONNACK ou le reason code au lieu de deviner.
  4. Utilisez un client ID unique et reconnectez-vous avec un backoff.
  5. Gardez le keep-alive plus court que tout délai d’inactivité sur le chemin.

Pour une procédure de test complète, suivez comment tester un broker MQTT.

Questions fréquentes

Que signifie l’erreur MQTT « connection refused: not authorized » ?

Le broker a accepté la connexion réseau mais a rejeté le client. En MQTT 3.1.1, c’est le code de retour CONNACK 5 ; en MQTT 5, le reason code 0x87. Les identifiants peuvent être valides, mais le compte n’a pas le droit de se connecter ou d’utiliser ce client ID.

Pourquoi mon client MQTT se déconnecte-t-il et se reconnecte-t-il sans cesse ?

La cause la plus fréquente est que deux clients utilisent le même client ID. Le broker déconnecte l’ancienne session chaque fois qu’une nouvelle se connecte avec cet ID, et si les deux se reconnectent automatiquement, ils s’éjectent mutuellement en boucle. Donnez un ID unique à chaque client.

Pourquoi ma connexion MQTT expire-t-elle au lieu d’échouer ?

Un timeout signifie qu’il n’y a eu aucune réponse, ce qui indique généralement un pare-feu qui ignore silencieusement les paquets, un mauvais hôte ou l’utilisation du port TCP depuis un navigateur. Un refus, à l’inverse, signifie que quelque chose a répondu et a dit non.