Algo que veo constantemente en flujos de n8n en producción que confunde a la gente.
Cuando habilitas Continue On Fail en un nodo, n8n marcará la ejecución como éxito aunque ese nodo falle con un 500, un 401 o una respuesta vacía. El error se pasa aguas abajo como datos de salida de error, el flujo sigue ejecutándose, y el estado de ejecución de nivel superior se muestra en verde.
Esto significa: tu nodo de HubSpot falló, tu fila de CRM nunca fue creada, tu cliente nunca recibió el email — y el registro de ejecución de n8n muestra éxito.
Tres lugares donde esto causa problemas reales:
-
Nodos HTTP Request con Continue On Fail — un 500 de una API se ve idéntico a un 200 en la vista de ejecución
-
Nodos de código que lanzan errores — pasados silenciosamente aguas abajo
-
Cualquier nodo en un flujo de múltiples pasos donde “solo quieres que siga adelante”
La solución es añadir un nodo IF explícito después de cualquier nodo crítico que use Continue On Fail — verifica la presencia de $json.error en la salida y enrútalo a una rama de alerta.
¿Alguien más ha encontrado esto en producción? Me gustaría saber cómo la gente lo está manejando en flujos más grandes.
buenas adiciones. la forma inconsistente del error confunde constantemente a la gente. manejar tanto $json.error.message como $json.error como una cadena simple en la misma comprobación IF es la decisión correcta.
el caso de cero elementos es más desagradable que CoF en algunos aspectos. sin forma de error, el flujo se detiene, todo lo anterior muestra verde. añado comprobaciones explícitas de recuento de elementos en nodos donde la salida vacía es un fallo real, no solo un caso extremo silencioso.
en la configuración: Error Trigger central para fallos obvios, pero eso deja sin cubrir los casos de CoF y cero elementos. he estado construyendo algo específicamente para el patrón verde pero roto. ¿cuál es el lugar más común donde los cero elementos causan problemas a la gente en producción?
Encontré exactamente este problema en producción con flujos de trabajo de reportes orientados al cliente. El patrón inline IF-after-CoF funciona, pero tiene una debilidad estructural: cada validación vive dentro del flujo que está verificando. Si el flujo se detiene temprano (tu caso de cero elementos), o alguien edita un nodo y elimina la rama de validación, la verificación muere con él — y todo lo que está aguas arriba sigue mostrando verde.
A lo que llegué: mantén las validaciones inline para el enrutamiento, pero mueve la validación de estado FUERA del flujo de trabajo. Cada flujo de trabajo en producción escribe una línea de metadatos de ejecución (estado, conteos de elementos, marca de tiempo) en una hoja de registro como último paso; un observador programado separado lee el registro y alerta sobre ejecuciones faltantes, filas de error o salidas con conteo cero. El observador sobrevive a cualquier cosa que suceda dentro de los flujos de trabajo que monitorea — incluyendo que no se ejecuten en absoluto, lo que ninguna validación inline jamás puede detectar.
Tengo curiosidad sobre a qué escala esto comienza a ser un problema para la gente — ¿cuántos flujos de trabajo en producción estabas ejecutando cuando estableciste tu disciplina de CoF?
@dima_automation Para cero elementos en producción - el lugar más común donde lo veo es en Google Sheets “Get Rows” con un filtro que no devuelve nada (token expirado, hoja renombrada, rango incorrecto). El flujo se ejecuta sin problemas con cero elementos, cada nodo descendente produce cero elementos, y el nodo de envío/escritura final simplemente nunca se ejecuta. Sin error, registro verde, el cliente no recibe informe. El segundo más común: paginación del nodo HTTP Request que sale temprano porque la API cambia el esquema de respuesta y la verificación “hay más páginas” devuelve falso. La solución que uso: después de cualquier nodo donde cero salida sería un fallo real, agrega un nodo IF verificando {{ $items().length === 0 }} y enruta eso a una alerta explícita en lugar de continuar silenciosamente.
Ambos son textuales, especialmente Sheets Get Rows con un filtro que discretamente no coincide con nada, aguas abajo todo cero, el envío final nunca se ejecuta, registro verde. Esta es la explicación más limpia de todo el problema que he visto.
El nodo IF comprobando {{ $items().length === 0 }} es la guardia de flujo correcta donde cero es inequívocamente un fallo. Una cosa que vale la pena señalar: captura tu primer caso pero no el segundo. La salida de paginación temprana devuelve un conjunto truncado pero distinto de cero, así que length === 0 lo pasa sin problemas, el flujo obtuvo 40 de 200 filas y cada nodo está felizmente no vacío. Ese necesita una expected-count o una verificación de línea base, aproximadamente es esto muy por debajo de lo que normalmente produce esta ejecución, no solo cero versus no.
Y ambos patrones aún asumen que la ejecución se disparó. La versión más desagradable es el flujo de trabajo programado que nunca se activó en absoluto, ningún nodo IF se ejecuta porque nada se ejecutó, nada se lee como cero porque nada fue ejecutado. Ese es el caso que me empujó hacia la verificación del resultado desde fuera de la ejecución, una guardia por nodo no puede proteger una ejecución que no sucedió. Tu verificación de cero más una línea base de conteo más una verificación de disponibilidad externa cubre la mayoría de la superficie entre ellos.