3 · Infraestructura·5 min de lectura
El vigilante que nunca vigiló
Julio: 803 de 859 mensajes analizados. Agosto: 209 de 895 — y 166 de esos eran errores guardados como si fueran análisis. Septiembre: 0 de 226.
El sistema no falló ni una vez. Respondía 200 OK, los tableros seguían verdes y cada ejecución terminaba en success. Por eso nadie lo revisó.
Qué hacía el sistema#
Capturaba los mensajes de los grupos internos de WhatsApp de una empresa, clasificaba cada uno y le pedía a un modelo de IA que juzgara si algo ameritaba avisar: un faltante, un cobro sin registrar, una venta por fuera.
Capturaba bien. Avisar, nunca avisó.
Tres fallas al mismo tiempo, y las tres decían "success"#
1 · El enrutador sin salida por defecto. Nueve reglas cubrían cotización, venta, producción, compra, cobro, inventario. Todo lo demás —imágenes, que eran el 52% de las capturas, más 302 mensajes de texto plano y 157 facturas— no caía en ninguna salida. n8n terminaba la ejecución sin enriquecer y marcándola como exitosa.
2 · Una llave leída desde el lugar equivocado. El nodo de código pedía la API key de Anthropic con $env. n8n bloquea el acceso a variables de entorno en nodos Code por omisión: devolvía "access to env vars denied", y al intentar envolver ese error reventaba con "Cannot assign to read only property". La ejecución entera moría antes de escribir el resultado.
3 · El proveedor retiró el modelo. Groq dio de baja todos los Llama. Cada llamada devolvía model_not_found. Y como el nodo estaba configurado con neverError, el fallo se convertía en un resultado vacío que seguía su camino: 8 de 8 ejecuciones "exitosas" sin una sola alerta.
Ese último punto es el que hay que subrayar. neverError se pone para poder leer el cuerpo de un error en vez de que el flujo muera sin explicar nada. Pero si nadie mira el código HTTP después, convierte cualquier falla en un éxito silencioso.
Qué hicimos#
Salida por defecto en el enrutador, para que ningún mensaje se caiga por no encajar. La llave por credencial de n8n, nunca por variable de entorno. Y el modelo migrado a uno vigente, probado antes de confiarle nada: JSON limpio en ~0.4 s.
De paso aparecieron cuatro referencias muertas al modelo retirado dentro del portal — en el motor de alertas, en el extractor de cotizaciones y en el generador de briefings. Ninguna había dado error visible.
Y el control que evita que se repita: cada automatización declara qué resultado debe dejar —una fila escrita, una alerta enviada— y un vigilante cruza lo que dice hacer contra lo que de verdad dejó. El veredicto que importa no es "corrió": es "corrió sin escribir".
Lo que nos llevamos#
Un 200 OK no es evidencia de nada. La falla ruidosa incomoda pero se atiende; la silenciosa se hereda. Y cuando un sistema lleva semanas sin reportar un solo problema, la primera hipótesis no debería ser que todo va bien.