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ôme | Niveau | Cause la plus probable |
|---|---|---|
Erreur ENOTFOUND / getaddrinfo | DNS | Faute de frappe dans le nom d’hôte, ou schéma d’URL inclus dans le champ hôte |
| Bloque, puis expire | Réseau | Pare-feu qui bloque le port, mauvais port, ou port TCP utilisé depuis un navigateur |
ECONNREFUSED | Réseau | Rien n’écoute sur cet hôte et ce port |
| Erreur de certificat ou de handshake | TLS | CA non reconnue, nom d’hôte non concordant, ou TLS vers un port en clair |
| Connexion fermée juste après la connexion | MQTT | CONNACK avec un code d’erreur — voir les tableaux ci-dessous |
| Se connecte, puis décroche à répétition | Session | Client 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 :
- Le port correspond au transport.
mqtt://sur 1883,mqtts://sur 8883,wss://sur le port WebSocket du broker. Voir les ports MQTT expliqués. - 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. - Le broker est en ligne. Les bacs à sable publics redémarrent sans préavis ; testez un autre broker pour écarter votre propre configuration.
- 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 :
| Code | Signification | Que corriger |
|---|---|---|
0 | Connexion acceptée | Rien — vous êtes connecté |
1 | Version de protocole inacceptable | Le broker ne prend pas en charge la version demandée ; basculez entre MQTT 3.1.1 et 5 |
2 | Identifiant rejeté | Le client ID est invalide, trop long, vide alors que ce n’est pas autorisé, ou bloqué |
3 | Serveur indisponible | Le broker est surchargé ou en maintenance ; réessayez avec un backoff |
4 | Nom d’utilisateur ou mot de passe incorrect | Vérifiez les identifiants et leur encodage |
5 | Non 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 :
| Code | Nom | Cause typique |
|---|---|---|
0x80 | Unspecified error | Échec générique ; consultez les logs du broker |
0x84 | Unsupported Protocol Version | Le broker ne parle que la 3.1.1 |
0x85 | Client Identifier not valid | Client ID mal formé ou non autorisé |
0x86 | Bad User Name or Password | Identifiants incorrects |
0x87 | Not authorized | Utilisateur valide sans permission de se connecter |
0x88 | Server unavailable | Le broker ne peut pas accepter de connexions pour le moment |
0x8A | Banned | Client ou IP bloqué par l’opérateur |
0x8C | Bad authentication method | Méthode d’authentification étendue non prise en charge |
0x95 | Packet too large | Le CONNECT dépasse la taille maximale de paquet du broker |
0x97 | Quota exceeded | Le compte a atteint une limite de connexions ou d’utilisation |
0x9F | Connection rate exceeded | Reconnexions 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 :
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
- Confirmez l’aller-retour sur un broker public fiable dans le client en ligne.
- Faites correspondre schéma, port et chemin au listener documenté du broker.
- Lisez le code CONNACK ou le reason code au lieu de deviner.
- Utilisez un client ID unique et reconnectez-vous avec un backoff.
- 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.