Cloud, DevOps e IoT en español

13 errores reales al construir domótica con ESP32 y AWS IoT (y cómo los resolví)

13 de octubre de 2026 · Steven Carvajal · Tutoriales

Código de este artículo en GitHub →

Montar un sistema de domótica con ESP32 y AWS IoT Core no es difícil por los conceptos. Lo difícil son los fallos silenciosos: el código compila, la librería dice que todo salió bien y aun así no pasa nada. Estos son los 13 errores que más horas me costaron, con el síntoma tal como lo vi, la causa real y la solución.

Cada error tiene su artículo propio con el detalle y el código; aquí va el resumen para encontrar rápido el tuyo.

Firmware del ESP32

1. "was not declared in this scope" con un struct que sí está declarado

Síntoma: el sketch no compila y el error apunta a un tipo que está definido unas líneas más arriba.

Causa: el IDE de Arduino genera prototipos de tus funciones y los inserta antes de la primera función que encuentra. Si esa "primera función" está antes de la definición del tipo (por ejemplo, una macro que se expande a una función), los prototipos usan un tipo que todavía no existe.

Solución: tipos en un .h incluido al principio y macros después de todos los #include. Detalle en el error de los prototipos automáticos de Arduino.

2. El ESP32-C3 se desconecta de AWS IoT un segundo después de conectar

Síntoma: conecta, AWS registra la desconexión con motivo CLIENT_ERROR y vuelve a empezar. El mismo firmware funciona en un ESP32-S3.

Causa: la pila (stack) de la tarea loop() se queda corta con TLS, MQTT y JSON a la vez, y la memoria se corrompe sin un reinicio que lo delate.

Solución: SET_LOOP_TASK_STACK_SIZE(16 * 1024);. Detalle en ESP32-C3 y CLIENT_ERROR por falta de stack.

3. publish() devuelve true y a AWS no llega nada

Síntoma: el monitor serie dice "publicado", pero el cliente de pruebas MQTT de AWS no recibe nada. La política, el tópico y el tamaño del búfer están bien.

Causa: con QoS 0, true solo significa que el mensaje se escribió en el búfer de red, no que llegó. En mi caso, PubSubClient con WiFiClientSecure en un ESP32-S3 perdía los mensajes.

Solución: cambiar a la librería MQTT de 256dpi y publicar con QoS 1. Detalle en ESP32 publica en MQTT pero no llega a AWS IoT.

4. softAPmacAddress() devuelve ceros en el ESP32-S3

Síntoma: el nombre de la red del portal de configuración sale con 0000 en vez del final de la MAC.

Causa: en el S3, la MAC del punto de acceso no está lista en el mismo instante en que llamas a WiFi.mode(WIFI_AP). En el C3 sí lo está, por eso el código "funcionaba".

Solución: una pausa corta antes de leerla:

WiFi.mode(WIFI_AP);
delay(100);
String mac = WiFi.softAPmacAddress();

Más sobre el portal en portal cautivo para configurar el Wi-Fi del ESP32.

ESP-NOW

5. esp_now_add_peer() falla a partir del dispositivo 21

Síntoma: los primeros 20 nodos funcionan; el siguiente no se puede registrar.

Causa: ESP-NOW admite como máximo 20 peers por dispositivo, y es un límite fijo.

Solución: broadcast, registrar peers solo al enviar o un segundo coordinador. Detalle en el límite de 20 dispositivos de ESP-NOW.

6. Un nodo que se reinicia pierde el último comando

Síntoma: apagas una luz desde la app mientras el nodo está sin corriente; cuando vuelve, enciende con el estado anterior.

Causa: al preguntar "¿cómo debo estar?", el coordinador respondía con el último estado confirmado, no con el último pedido.

Solución: guardar los dos estados y responder con el deseado. Detalle en comandos perdidos al reconectar un nodo ESP-NOW.

MQTT y Device Shadow

7. El WebSocket a AWS IoT se cierra con código 1006

Síntoma: el navegador abre el WebSocket y se cierra al instante, sin mensaje.

Causa: el token de sesión (X-Amz-Security-Token) se incluyó en la firma SigV4. En AWS IoT va fuera de la firma.

Solución: firmar sin el token y añadirlo al final de la URL. Detalle en WebSocket de AWS IoT cerrado con 1006.

8. Al iniciar sesión, todos los interruptores aparecen apagados

Síntoma: el estado real está bien en AWS, pero la app muestra todo apagado de vez en cuando.

Causa: la app publicaba la petición de estado antes de que la suscripción a la respuesta estuviera activa. La respuesta llegaba y nadie la escuchaba.

Solución: esperar el SUBACK. Detalle en respuesta MQTT perdida por no esperar el SUBACK.

9. La luz vuelve sola al estado anterior un segundo después

Síntoma: cambias la luz con el interruptor físico y, un segundo después, vuelve como estaba.

Causa: el dispositivo reportó el nuevo estado, pero desired seguía con el valor viejo. AWS generó un delta y el dispositivo lo "corrigió".

10. La app muestra encendido algo que nunca se encendió

Síntoma: con el dispositivo desconectado, el interruptor de la app se queda en "encendido" para siempre.

Causa: la app pintaba desired cuando no llegaba reported.

Solución de 9 y 10 en errores de desired y reported en el Device Shadow.

Login y web app

11. Cognito Identity Pool no entrega credenciales

Síntoma: el login con el User Pool funciona, pero el paso de pedir credenciales de AWS falla con NotAuthorizedException.

Causa: el User Pool no estaba vinculado a la Identity Pool como proveedor de identidad.

Solución: vincularlo con el ID del app client. Detalle en Identity Pool que no entrega credenciales.

12. "Olvidé mi contraseña" no envía el código

Síntoma: a un usuario creado por el administrador nunca le llega el código de recuperación.

Causa: sigue en estado FORCE_CHANGE_PASSWORD porque nunca completó su primer inicio de sesión.

Solución: contraseña permanente al crearlo o completar el reto NEW_PASSWORD_REQUIRED. Ver login con Cognito y FORCE_CHANGE_PASSWORD.

13. La PWA no se actualiza aunque publiques una versión nueva

Síntoma: despliegas y los usuarios siguen viendo la versión anterior durante días.

Causa: el registro por defecto del service worker se ejecuta una vez y nunca vuelve a comprobar.

Solución: registro explícito con chequeo periódico. Ver PWA con Vite que se actualiza.

Lo que aprendí de estos 13 errores

Si estás empezando, la guía del ESP32 y la serie de domótica con ESP32 y AWS explican cómo encaja todo.

Preguntas frecuentes

¿Cómo veo por qué AWS IoT desconectó mi ESP32?

Activa los registros de AWS IoT en CloudWatch o suscríbete a los eventos de ciclo de vida ($aws/events/presence/disconnected/+). El campo disconnectReason dice el motivo: CLIENT_ERROR, DUPLICATE_CLIENTID, AUTH_ERROR, etc.

¿Estos errores pasan también con otros brokers MQTT?

Los de firmware, ESP-NOW y SUBACK, sí. Los del Shadow, la firma SigV4 y Cognito son propios de AWS.

Sigue leyendo

Guía completa de esp32 y firmware: Qué es el ESP32 y por qué domina los proyectos IoT: guía para elegir y empezar