Fundamentos de MQTT

Códigos de motivo de MQTT 5 (reason codes): tabla de referencia completa con causas y soluciones

Todos los códigos de motivo (reason codes) de MQTT 5 en una tabla, agrupados por los paquetes que los transportan, con sus causas habituales y soluciones prácticas. Incluye la equivalencia con los códigos de retorno de MQTT 3.1.1 y código Python para registrarlos correctamente.

Tabla de referencia de códigos de motivo MQTT en hexadecimal agrupados por tipo de paquete en una consola de depuración
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Los códigos de motivo de MQTT (reason codes) son los valores de estado de un solo byte que los brokers y clientes MQTT 5 incluyen en los acuses de recibo y en los paquetes DISCONNECT para indicar exactamente qué ha ocurrido. Esta referencia recoge todos los códigos, qué paquetes pueden transportarlos, qué suele provocarlos y cómo resolverlos, para que puedas convertir un críptico 0x87 o 0x97 en tus registros en un siguiente paso concreto.

Cómo funcionan los códigos de motivo de MQTT

MQTT 3.1.1 solo tenía un puñado de valores de estado: seis códigos de retorno de CONNACK y un único valor de fallo (0x80) en SUBACK. Todo lo demás, como una publicación rechazada o una desconexión iniciada por el broker, era silencioso; la conexión simplemente se cerraba. MQTT 5 lo sustituyó por un conjunto compartido de reason codes que se usa en CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT y AUTH. Es una de las funciones de MQTT 5 más prácticas para cualquiera que opere dispositivos en campo.

Dos reglas facilitan la lectura de la tabla:

  • Los valores por debajo de 0x80 indican éxito o un resultado que no es un error, como "QoS 1 concedido" o "no hay suscriptores coincidentes".
  • Los valores de 0x80 en adelante indican fallo. El paquete que transporta el código te dice qué operación ha fallado.

Muchos paquetes también pueden llevar una propiedad Reason String, una explicación legible del emisor. Regístrala siempre que aparezca; a menudo contiene el límite exacto que se ha alcanzado.

Códigos de éxito e informativos

Código Nombre Paquetes Qué significa
0x00 Success / Normal disconnection / Granted QoS 0 CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH, DISCONNECT, SUBACK La operación tuvo éxito; en SUBACK significa que la suscripción se concedió con QoS 0
0x01 Granted QoS 1 SUBACK Suscripción aceptada con QoS máximo 1
0x02 Granted QoS 2 SUBACK Suscripción aceptada con QoS máximo 2
0x04 Disconnect with Will Message DISCONNECT El cliente se desconecta limpiamente pero pide al broker que publique su Will
0x10 No matching subscribers PUBACK, PUBREC Publicación aceptada, pero nadie estaba suscrito
0x11 No subscription existed UNSUBACK Te diste de baja de un filtro al que no estabas suscrito
0x18 Continue authentication AUTH Continúa el intercambio de autenticación mejorada
0x19 Re-authenticate AUTH El cliente inicia una reautenticación en una conexión existente

Un SUBACK que concede un QoS inferior al solicitado no es un error. Si pides QoS 2 y recibes 0x01, el QoS máximo del broker para tu conexión es 1, y los mensajes llegarán como mucho con QoS 1.

Referencia de códigos de error

Código Nombre Paquetes Causa habitual Solución
0x80 Unspecified error Todos los acuses de recibo, DISCONNECT El broker rechazó la operación sin un motivo concreto Lee la Reason String y los registros del broker
0x81 Malformed Packet CONNACK, DISCONNECT Codificación no válida, UTF-8 incorrecto, longitudes erróneas Actualiza la librería cliente; revisa los codificadores propios
0x82 Protocol Error CONNACK, DISCONNECT Paquete válido pero enviado en el orden incorrecto o con campos prohibidos Busca CONNECT duplicados o un mal uso de las propiedades
0x83 Implementation specific error CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT Una política propia del broker rechazó la operación Consulta la documentación del broker y la Reason String
0x84 Unsupported Protocol Version CONNACK El broker no habla la versión solicitada Usa MQTT 3.1.1 o 5.0 según lo que se admita
0x85 Client Identifier not valid CONNACK Client ID vacío, demasiado largo o no permitido Usa un client ID válido y único
0x86 Bad User Name or Password CONNACK Credenciales incorrectas o mal formadas Vuelve a copiar el usuario y la contraseña
0x87 Not authorized CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT Las credenciales o el cliente carecen de permiso Revisa las credenciales, la vinculación del client ID y los permisos sobre topics
0x88 Server unavailable CONNACK El broker no puede aceptar conexiones en este momento Reintenta con backoff
0x89 Server busy CONNACK, DISCONNECT El broker está sobrecargado Reintenta más tarde con backoff y jitter
0x8A Banned CONNACK El cliente o la dirección están bloqueados Detén los bucles de reintento; corrige las credenciales; contacta con el operador
0x8B Server shutting down DISCONNECT Apagado o reinicio planificado Reconéctate con backoff
0x8C Bad authentication method CONNACK, DISCONNECT Método de autenticación mejorada no admitido Elimina o corrige el Authentication Method
0x8D Keep Alive timeout DISCONNECT No se recibió ningún paquete en 1,5 x keep alive Atiende el bucle de red; comprueba la conectividad
0x8E Session taken over DISCONNECT Otro cliente se conectó con el mismo client ID Da a cada cliente un ID único
0x8F Topic Filter invalid SUBACK, UNSUBACK, DISCONNECT Filtro mal formado, p. ej. a/#/b Corrige la posición de los comodines
0x90 Topic Name invalid CONNACK, PUBACK, PUBREC, DISCONNECT Comodines o caracteres no válidos en un topic de publicación Publica en un nombre de topic concreto
0x91 Packet Identifier in use PUBACK, PUBREC, SUBACK, UNSUBACK ID de paquete reutilizado mientras seguía en vuelo Fallo de la librería o gestión propia de los ID de paquete
0x92 Packet Identifier not found PUBREL, PUBCOMP Estado de QoS 2 perdido, a menudo tras un reinicio de sesión Revisa la configuración de persistencia de sesión
0x93 Receive Maximum exceeded DISCONNECT Demasiadas publicaciones QoS 1/2 sin confirmar Respeta el Receive Maximum del otro extremo
0x94 Topic Alias invalid DISCONNECT Alias fuera de rango o no definido Reinicia los alias al reconectar; respeta el máximo
0x95 Packet too large CONNACK, DISCONNECT El paquete supera el Maximum Packet Size Reduce o trocea los payloads
0x96 Message rate too high DISCONNECT Publicación más rápida de lo permitido Limita el ritmo de publicación
0x97 Quota exceeded CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT Se alcanzó un límite del plan o de la cuenta Reduce el uso o mejora el plan
0x98 Administrative action DISCONNECT Un operador desconectó al cliente Consúltalo con el administrador del broker
0x99 Payload format invalid CONNACK, PUBACK, PUBREC, DISCONNECT El Payload Format Indicator indica UTF-8 pero los bytes no lo son Corrige la codificación o elimina el indicador
0x9A Retain not supported CONNACK, DISCONNECT Flag retain usado donde no está permitido Publica sin retain
0x9B QoS not supported CONNACK, DISCONNECT QoS de publicación superior al máximo del broker Baja el QoS al máximo anunciado
0x9C Use another server CONNACK, DISCONNECT El broker redirige al cliente temporalmente Sigue la propiedad Server Reference
0x9D Server moved CONNACK, DISCONNECT El broker redirige de forma permanente Actualiza el host configurado
0x9E Shared Subscriptions not supported SUBACK, DISCONNECT Filtro $share/... no permitido Usa un plan o un broker con suscripciones compartidas
0x9F Connection rate exceeded CONNACK Demasiados intentos de conexión Añade backoff a la lógica de reconexión
0xA0 Maximum connect time DISCONNECT Se alcanzó el límite de duración de la conexión Reconéctate; cuenta con desconexiones periódicas
0xA1 Subscription Identifiers not supported SUBACK, DISCONNECT Propiedad Subscription Identifier no permitida Elimina la propiedad
0xA2 Wildcard Subscriptions not supported SUBACK, DISCONNECT Comodines no permitidos para este cliente Suscríbete a topics explícitos

Ten en cuenta que algunos códigos, como 0x8D y 0x8E, solo aparecen en un DISCONNECT enviado por el broker. Otros, como los de 0x84 a 0x88, solo pueden aparecer en CONNACK, porque describen por qué se rechazó la conexión desde el principio.

Equivalencia entre los códigos de retorno de MQTT 3.1.1 y MQTT 5

Si admites ambas versiones del protocolo, esta equivalencia mantiene coherente tu gestión de errores. La explicación detallada está en la guía de códigos de retorno CONNACK de MQTT.

CONNACK de MQTT 3.1.1 Equivalente en 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

Registrar los códigos de motivo MQTT en Python

Con paho-mqtt 2.x y CallbackAPIVersion.VERSION2, cada callback recibe un objeto ReasonCode. Su forma de cadena es el nombre de la especificación y .value es el código numérico, justo lo que quieres en los registros:

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()

Ejecútalo contra el servidor MQTT público gratuito de broker.connectmq.com (pensado para pruebas y prototipos, no para datos de producción) y verás Success al conectar y un QoS concedido en el SUBACK. Prueba a suscribirte a un filtro no válido como connectmq/demo/b7d2/#/x para ver 0x8F Topic Filter invalid en acción. Con MQTT.js, la misma información está en connack.reasonCode, en el array granted del callback de suscripción y en el paquete del evento disconnect.

Flujo de depuración según el código de motivo

Un orden práctico para investigar un fallo:

  1. Identifica el paquete. Un código en CONNACK es un problema de conexión; en SUBACK, un problema de suscripción; en DISCONNECT, un problema en tiempo de ejecución.
  2. Lee la Reason String. Normalmente reduce la causa a un límite o una regla concretos.
  3. Comprueba primero las credenciales y la identidad para 0x85, 0x86 y 0x87. La guía para resolver MQTT connection refused: not authorized lo trata en profundidad.
  4. Comprueba los límites para 0x93, 0x95, 0x96 y 0x97: tamaño de mensaje, ritmo, número de conexiones y mensajes en vuelo.
  5. Comprueba la higiene de la flota para 0x8E: los client ID duplicados son la causa más habitual de los bucles de desconexión.

Códigos de motivo en ConnectMQ

ConnectMQ admite MQTT 3.1.1 y 5.0, así que los clientes MQTT 5 reciben los reason codes anteriores. Las cuotas del plan aparecen como 0x97 Quota exceeded, por ejemplo cuando un broker Serverless gratuito ya tiene su máximo de 25 conexiones. Las funciones del plan también importan: el plan gratuito concede QoS hasta 1, así que una suscripción con QoS 2 se concede con un QoS inferior en el SUBACK, mientras que QoS 2 y las suscripciones compartidas llegan con el plan Serverless de pago. Los inicios de sesión fallidos repetidos se tratan como sospechosos y la IP de origen puede bloquearse, así que nunca dejes un cliente reintentando con credenciales erróneas en un bucle cerrado.

Para saber más sobre qué hace un broker MQTT con estos códigos, o ver el protocolo completo en contexto, consulta el tutorial de MQTT.

Depura más rápido con ConnectMQ

Un broker MQTT gestionado con cliente en el navegador y explorador de topics en directo hace mucho más rápido reproducir una publicación o suscripción que falla. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y prueba tu gestión de errores con respuestas reales de MQTT 5.

Preguntas frecuentes

¿Qué diferencia hay entre un código de motivo y un código de retorno?

Código de retorno (return code) es el término de MQTT 3.1.1 para los seis valores de CONNACK. MQTT 5 generalizó la idea en códigos de motivo (reason codes) que aparecen en casi todos los acuses de recibo y en DISCONNECT.

¿Qué códigos de motivo indican éxito?

Cualquier valor por debajo de 0x80. Eso incluye 0x00 Success, 0x01 y 0x02 para el QoS concedido y valores informativos como 0x10 No matching subscribers.

¿Qué significa el código de motivo MQTT 0x97?

0x97 es Quota exceeded: el cliente alcanzó un límite, como el máximo de conexiones o una restricción del plan. Reduce el uso o pásate a un plan con límites más altos.

¿Reciben los clientes MQTT 3.1.1 los códigos de motivo de MQTT 5?

No. Una conexión 3.1.1 solo recibe los códigos de retorno clásicos de CONNACK y el valor de fallo 0x80 en SUBACK. Conéctate con la versión 5 del protocolo para recibir códigos de motivo detallados.

Artículos relacionados

¿Quién inventó MQTT? La historia, de los oleoductos al IoT

MQTT lo inventaron en 1999 Andy Stanford-Clark, de IBM, y Arlen Nipper, de Arcom, para monitorizar oleoductos vía satélite. Sigue su camino hacia el open source, OASIS, ISO y los brokers MQTT gestionados en la nube de hoy.

8 min de lectura

Por qué tu cliente MQTT se desconecta constantemente (y cómo solucionarlo)

Los bucles de reconexión son uno de los problemas más habituales de MQTT. Conoce las cinco causas típicas, desde los client ID duplicados hasta los timeouts de keep alive y los paquetes demasiado grandes, y sigue un flujo de diagnóstico que localiza la tuya.

9 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.