Los códigos de retorno CONNACK de MQTT son los seis valores, del 0 al 5, que un broker MQTT 3.1.1 devuelve para indicar a un cliente si se ha aceptado su conexión y, si no, por qué. Esta guía explica cada código, muestra cómo aparece en las herramientas y librerías habituales y te da una solución que puedes aplicar en minutos, con ejemplos contra el servidor MQTT público gratuito, pensado solo para pruebas, y contra un broker privado.
Qué contiene el paquete CONNACK
Después de que un cliente abre una conexión TCP, su primer paquete debe ser CONNECT. El broker responde con CONNACK, un paquete fijo de cuatro bytes en MQTT 3.1.1:
20 02 00 05
| | | |
| | | +-- Código de retorno de la conexión (aquí 5 = Not authorized)
| | +----- Flags de confirmación de conexión (bit 0 = Session Present)
| +-------- Longitud restante (siempre 2)
+----------- Tipo de paquete 2 (CONNACK), flags 0
El flag Session Present indica al cliente si el broker ha reanudado una sesión almacenada, algo importante para las sesiones persistentes. El código de retorno es el tema de este artículo. Si es distinto de 0, el broker cierra la conexión de red justo después de enviar el CONNACK, y el cliente debe corregir la causa antes de volver a intentarlo. Para ver la estructura completa de bytes de este y otros paquetes, consulta la guía de estructura de los paquetes MQTT.
Los códigos de retorno CONNACK de MQTT de un vistazo
| Código | Nombre | Causa típica | Lo primero que hay que comprobar |
|---|---|---|---|
| 0 | Connection accepted | Todo está bien | Nada |
| 1 | Unacceptable protocol version | El cliente pidió una versión que el broker no admite | Configuración de la versión del protocolo |
| 2 | Identifier rejected | Client ID vacío, no válido o no permitido | Valor del client ID |
| 3 | Server unavailable | El broker no puede atender la conexión en este momento | Estado del broker; reintenta con backoff |
| 4 | Bad user name or password | Credenciales incorrectas o mal formadas | Usuario y contraseña |
| 5 | Not authorized | El cliente no tiene permiso para conectarse | Credenciales, client ID, cuenta |
Los valores del 6 al 255 están reservados en MQTT 3.1.1. Si tu librería informa de alguno de ellos, normalmente está decodificando por error un reason code de MQTT 5, lo que significa que el cliente y el broker no coinciden en la versión del protocolo.
Cómo aparece cada código de retorno en tus herramientas
Los mensajes de error varían según la herramienta, lo que complica buscarlos. Así es como se ven los mismos códigos en tres clientes habituales:
| Código | mosquitto_pub / mosquitto_sub | reason_code de Paho Python 2.x | Mensaje de error de MQTT.js |
|---|---|---|---|
| 1 | Connection Refused: unacceptable protocol version | Unsupported protocol version | Connection refused: Unacceptable protocol version |
| 2 | Connection Refused: identifier rejected | Client identifier not valid | Connection refused: Identifier rejected |
| 3 | Connection Refused: broker unavailable | Server unavailable | Connection refused: Server unavailable |
| 4 | Connection Refused: bad user name or password | Bad user name or password | Connection refused: Bad username or password |
| 5 | Connection Refused: not authorised | Not authorized | Connection refused: Not authorized |
Paho asigna internamente los códigos de 3.1.1 a los nombres de reason codes de MQTT 5, así que puedes ver la redacción de MQTT 5 incluso en una conexión 3.1.1. La referencia de reason codes de MQTT muestra la equivalencia completa.
Código 1: Unacceptable Protocol Version
El paquete CONNECT lleva un byte de nivel de protocolo: 4 para MQTT 3.1.1, 5 para MQTT 5.0 y 3 para el antiguo MQTT 3.1. Si el broker no admite el nivel solicitado, responde con el código 1.
Cómo resolverlo:
- Fija la versión del protocolo de forma explícita en lugar de confiar en los valores por defecto de la librería. En las herramientas de Mosquitto usa
-V mqttv311o-V mqttv5, en Paho usaprotocol=mqtt.MQTTv311y en MQTT.js usaprotocolVersion: 4o5. - Evita MQTT 3.1 (nivel 3). Los brokers MQTT gestionados modernos como ConnectMQ admiten 3.1.1 y 5.0.
- Si estás detrás de un proxy o una pasarela, confirma que deja pasar MQTT sin modificarlo.
Código 2: Identifier Rejected
El broker no aceptó el identificador del cliente. Motivos habituales:
- Client ID vacío con clean session desactivado. MQTT 3.1.1 solo permite un client ID de longitud cero junto con clean session, y muchos brokers rechazan directamente los ID vacíos. Define siempre un ID no vacío.
- Caracteres o longitud fuera de las reglas del broker. Limítate a letras, dígitos y guiones, y mantén los ID razonablemente cortos.
- Client ID vinculado a las credenciales. Algunos brokers vinculan un client ID a una cuenta concreta. En un broker privado de ConnectMQ, los client ID están vinculados a las credenciales emitidas en el portal, así que usa el client ID que aparece allí junto con su usuario.
En el servidor MQTT público gratuito de broker.connectmq.com sirve cualquier ID no vacío y único. La guía del client ID de MQTT cubre estrategias de nomenclatura para flotas.
Código 3: Server Unavailable
La conexión de red funcionó, pero el broker no puede atender MQTT en este momento. Suele ser transitorio: un reinicio, una sobrecarga o un mantenimiento. Implementa un backoff exponencial con jitter en lugar de reconectar de inmediato; miles de dispositivos reconectándose a la vez pueden mantener sobrecargado a un broker que se está recuperando.
Código 4: Bad User Name or Password
El broker comprobó las credenciales y no coincidían. En la práctica:
- Vuelve a copiar el usuario y la contraseña desde la fuente original; los espacios finales y los campos intercambiados son frecuentes.
- Comprueba que tu librería envía realmente la contraseña. Algunas API exigen llamar a
username_pw_set()antes deconnect(). - Vigila que el entrecomillado del shell no altere los caracteres especiales de las contraseñas. Enciérralas entre comillas simples en la línea de comandos.
- No reintentes en bucle tras un fallo. Los brokers suelen protegerse frente a ataques de fuerza bruta, y ConnectMQ bloquea una dirección IP tras varios inicios de sesión fallidos.
Código 5: Not Authorized
El broker sabe quién eres pero rechaza la conexión. Entre las causas están usar credenciales de otro broker, un client ID que no coincide, una cuenta desactivada o una cuota agotada. Es el rechazo más habitual en los brokers privados y tiene su propia lista paso a paso en cómo resolver MQTT connection refused: not authorized.
Reproducir los códigos CONNACK de forma segura
Ver los códigos por ti mismo facilita reconocerlos en los registros de producción. Primero, una conexión correcta al servidor MQTT público gratuito (recuerda que es un entorno de pruebas, no para datos de producción), con la salida de depuración activada:
mosquitto_sub -h broker.connectmq.com -p 1883 -i connack-test-4e8b \
-t "connectmq/demo/4e8b/#" -V mqttv311 -d
El flag -d imprime Client connack-test-4e8b received CONNACK (0), con el código de retorno entre paréntesis. Contra un broker privado, una contraseña errónea a propósito muestra el rechazo:
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-u YOUR_USERNAME -P wrong-password -i YOUR_CLIENT_ID \
-t "test/#" -V mqttv311 -d
Ejecútalo solo una o dos veces; los fallos repetidos pueden provocar el bloqueo de la IP.
Gestionar los códigos de retorno en Python
Este cliente con paho-mqtt 2.x se conecta con MQTT 3.1.1, registra el código y se detiene en lugar de reintentar ante errores que requieren atención humana:
import paho.mqtt.client as mqtt
# Paho asigna los códigos 1, 2, 4 y 5 de 3.1.1 a los valores 0x84, 0x85, 0x86 y 0x87 de MQTT 5
FATAL = {0x84, 0x85, 0x86, 0x87}
def on_connect(client, userdata, flags, reason_code, properties):
if not reason_code.is_failure:
print("Connected, session present:", flags.session_present)
client.subscribe("connectmq/demo/4e8b/#")
return
print(f"Connection refused: {reason_code}")
if reason_code.value in FATAL:
print("Configuration problem, not retrying")
client.disconnect()
client.loop_stop()
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id="connack-py-4e8b",
protocol=mqtt.MQTTv311,
)
client.on_connect = on_connect
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_forever()
Gestionar los códigos de retorno en Node.js
MQTT.js emite un evento error con una propiedad code que contiene el valor numérico del CONNACK:
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
clientId: "YOUR_CLIENT_ID",
username: "YOUR_USERNAME",
password: "YOUR_PASSWORD",
protocolVersion: 4,
reconnectPeriod: 5000,
});
client.on("connect", () => console.log("CONNACK 0: connected"));
client.on("error", (err) => {
console.error(`CONNACK ${err.code}: ${err.message}`);
if ([1, 2, 4, 5].includes(err.code)) {
client.end(true); // dejar de reconectar ante errores de configuración
}
});
Lista rápida para resolver problemas de CONNACK
- ¿Puedes llegar al host y al puerto? Un timeout significa que nunca se envió un CONNACK; revisa el DNS, el firewall y el puerto.
- ¿Usas TLS en el 8883 y TCP sin cifrar en el 1883, y no al revés?
- ¿La versión del protocolo es explícita y está admitida?
- ¿El client ID no está vacío, es único y es el emitido con tus credenciales?
- ¿El usuario y la contraseña son exactamente los emitidos?
- ¿Tu lógica de reconexión se detiene ante los códigos 1, 2, 4 y 5 en lugar de machacar al broker?
Obtén respuestas de conexión claras con ConnectMQ
ConnectMQ es un broker MQTT gestionado que admite MQTT 3.1.1 y 5.0 sobre TCP 1883, TLS 8883 y WebSockets. El portal genera para cada broker un usuario, una contraseña y un client ID que encajan entre sí, lo que elimina la causa más habitual de los códigos 2, 4 y 5. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito. ¿Eres nuevo con los brokers? Empieza por qué hace un broker MQTT o por el tutorial de MQTT completo.
Preguntas frecuentes
¿Qué significa el código de retorno CONNACK 0?
Conexión aceptada. El broker ha aceptado el CONNECT, y el flag Session Present del mismo paquete te indica si se ha reanudado una sesión anterior.
¿Qué diferencia hay entre los códigos de retorno 4 y 5?
El código 4 significa que el usuario o la contraseña no coincidían. El código 5 significa que el broker rechaza al cliente por otro motivo de autorización, como un client ID no vinculado a esas credenciales o una cuenta que no tiene permiso para conectarse.
¿Por qué mi cliente no recibe ningún CONNACK?
Si no llega ningún CONNACK, el problema está por debajo de MQTT: host o puerto erróneos, un firewall o una discrepancia de TLS, como MQTT sin cifrar enviado al puerto 8883. Resuelve la conectividad antes de mirar los códigos de retorno.
¿Usa MQTT 5 los mismos códigos CONNACK?
No. MQTT 5 los sustituye por reason codes como 0x86 y 0x87, que aportan más detalle. Los seis códigos de 3.1.1 tienen equivalencia directa en MQTT 5.



