# Códigos de error: Workflows: causas de fallo al ejecutar

> Una action que sabe por qué falló lanza `WorkflowActionError` con una causa (`src/workflows/engine/workflow-action-error.ts`); el motor la guarda en `workflow_execution_logs.details_json.cause` y deja la ejecución o el paso en error. Algunas causas las pone el motor mismo (`automation_session_dead`, `enqueue_failed`, `zombie_running_no_heartbeat`).

**Cómo se detecta (toda la familia):** Render: `[WORKFLOW-ACTION] cause=<causa> execution=<id> entity=<id> workflow=<id>`. Base: `workflow_execution_logs` con `JSON_EXTRACT(details_json,'$.cause')`. CLI: `yarn -s wf reporte` y la skill `revisar-workflows` los cuentan por causa.

**Qué hacer (toda la familia):** Casi siempre es la configuración del workflow (falta un paso antes, una etiqueta que no existe, una plantilla de otro número): corrígela con la skill `cambiar-workflow`. Si es del motor, la skill `debug-workflow`.

Lo que un código no dice lo hereda de la familia.

## `agency_id_missing`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** `crm.assign_seller_by_agency` en modo agencia específica no tiene la agencia configurada.

## `agency_not_in_reply`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El cliente no eligió una agencia de la lista (contestó texto libre), así que no se puede asignar vendedor por agencia.

## `agency_not_quotable`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La agencia elegida ya no es cotizable en la entidad (dejó de estar activa o cotizable en Zauru).

## `agenda_config_invalid`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La configuración de `agenda.create_event` es inválida (fecha, hora o tipo).

## `agenda_lead_missing`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** `agenda.create_event` no tiene un lead en el contexto.
- **Qué hacer:** Agregar antes un paso que traiga el cliente (p. ej. «Buscar cliente») o usar un trigger que lo traiga.

## `agenda_seller_missing`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** `agenda.create_event` no tiene un vendedor asignado en el contexto.
- **Causa típica:** El paso corre antes de «Asignar vendedor», o el lead no tiene vendedor. La causa de workflow más frecuente de septiembre de 2026.
- **Qué hacer:** Agregar «Asignar vendedor» antes del paso, o elegir un vendedor específico en la configuración del evento.

## `automation_session_dead`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El usuario de automatización del workflow (`entity_workflow_configs`) no tiene una sesión viva en Zauru: nada que toque Zauru puede correr.
- **Causa típica:** La sesión del usuario API de la entidad venció o su apikey cambió.
- **Cómo detectarlo:** Render: `[SESION_ZAURU_AUTOMATIZACION]` y `[WORKFLOW-ACTION] cause=automation_session_dead`.
- **Qué hacer:** Renovar la sesión del usuario de automatización de esa entidad (plataforma). Las ejecuciones que fallaron no se reintentan solas.

## `channel_account_forbidden`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El workflow no tiene permitido enviar la plantilla por ese número.

## `channel_account_not_configured`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El número emisor de la plantilla no tiene configurado su emisor (sender).

## `COMMENT_REPLY_EMPTY`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El texto de `comments.reply` quedó vacío después de reemplazar las variables. Detiene el paso sin mandar nada.
- **Qué hacer:** Escribir el texto de la respuesta o revisar que las variables que usa (`{{trigger.author_name}}`…) tengan valor.

## `COMMENT_TRIGGER_REQUIRED`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** `comments.reply` o `comments.hide` corrió en un workflow que no es `comment.created`: no hay `trigger.comment_id` al que responder u ocultar. Detiene el paso.
- **Qué hacer:** Usar esas actions solo en workflows con trigger `comment.created` (un comentario de Facebook o Instagram).

## `enqueue_failed`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** No se pudo encolar la continuación de la ejecución en SQS: la ejecución queda en pausa con error.

## `list_channel_not_supported`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** `comms.send_list` solo funciona por WhatsApp y el chat es de otro canal.

## `list_without_rows`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** comms.send_list no tiene filas que ofrecer

## `no_conversation`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Enviar producto: no hay chat en el contexto para mandar el producto (queda como `comms.*.error`, el flujo sigue).

## `no_invoice_items`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Enviar producto: la factura del contexto no trae líneas (el flujo sigue con el error en el contexto).

## `no_sellers_in_agency`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La agencia elegida no tiene vendedores asignados en Zauru.

## `out_of_stock`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Enviar producto: el producto elegido no tiene existencia; no se envía (el flujo sigue con el error en el contexto).

## `product_not_found`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Enviar producto: no se encontró el producto elegido en el catálogo (el flujo sigue con el error en el contexto).

## `REACTION_CHANNEL_NOT_SUPPORTED`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** `comms.send_reaction` no puede reaccionar por el canal de la conversación: correo, comentarios u otro canal sin reacciones, o una cuenta de Messenger/Instagram que no sale por la salida directa de Boost. Detiene el paso (es un error de configuración, no de ventana).
- **Qué hacer:** Usar la reacción solo en flujos de WhatsApp, o en Messenger/Instagram con la cuenta en salida directa de Boost (`egress_owner = boost`).

## `REACTION_EMOJI_INVALID`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El emoji configurado en `comms.send_reaction` está vacío o no sirve (más de 32 caracteres). Detiene el paso.
- **Qué hacer:** Elegir uno de la lista (👍 ❤️ 😂 😮 😢 🙏) o un emoji de hasta 32 caracteres.

## `SEND_SKIPPED_DUPLICATE_KEY`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Un envío repetido de la misma ejecución, paso y mensaje no salió: la llave de envío (`sk1:`) ya existía. Protege de mensajes dobles; no es un fallo.
- **Cómo detectarlo:** Render: `send_key sk1:…: envio repetido … no se reenvia`. Base: `workflow_execution_logs` con este `cause`.
- **Qué hacer:** Nada, salvo que el primer envío haya fallado de verdad: entonces revisar ese primer intento.

## `template_header_media_invalid`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Meta rechazó el archivo del encabezado de la plantilla.

## `template_header_media_missing`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La plantilla tiene encabezado de imagen, video o documento y no se resolvió el archivo.

## `template_missing_for_channel_account`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La variante del número emisor no tiene plantilla elegida.

## `template_not_in_waba`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La plantilla no existe o no está aprobada en la WABA del número que envía.
- **Causa típica:** Una plantilla pertenece a la WABA de un solo número: se eligió la de otro número, o Meta la rechazó o la pausó.
- **Qué hacer:** Elegir la plantilla correcta para cada número en el paso (plantilla por número).

## `template_param_count_mismatch`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La plantilla recibió un número de variables distinto al que espera Meta.

## `workflow_action_tree_too_deep`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El motor se negó a correr una action más honda que el tope de anidamiento (10 niveles).

## `workflow_branch_path_unnavigable`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El motor no pudo seguir la ruta de ramas guardada en la ejecución: el workflow cambió mientras la ejecución esperaba y la rama ya no existe.

## `workflow_contact_label_missing_contact`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Poner etiqueta de contacto: no hay contacto en el contexto (falta «Buscar cliente» antes o un trigger que lo traiga).

## `workflow_contact_label_missing_label`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Poner etiqueta de contacto: el paso no tiene elegida la etiqueta.

## `workflow_contact_label_not_found`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Poner etiqueta de contacto: la etiqueta elegida ya no existe (la borraron); hay que volver a elegirla.

## `workflow_fan_out_trigger_not_allowed`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El motor se negó a repartir (fan-out) porque el trigger del workflow no lo permite; el guardado ya lo impide, esto cubre lo guardado antes.

## `workflow_group_label_missing_group`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Poner etiqueta de grupo: no hay cliente (grupo) en el contexto.

## `workflow_group_label_missing_label`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Poner etiqueta de grupo: el paso no tiene elegida la etiqueta.

## `workflow_group_label_not_found`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Poner etiqueta de grupo: la etiqueta elegida ya no existe; hay que volver a elegirla.

## `workflow_invoice_field_empty_value`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: la ruta del valor no tiene nada en el contexto (¿corre antes de que llegue la respuesta?).

## `workflow_invoice_field_invalid_value`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: el valor no es del tipo del campo (p. ej. no es numérico).

## `workflow_invoice_field_missing_config`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: falta un dato obligatorio en la configuración del paso.

## `workflow_invoice_field_missing_name`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: falta el nombre (el texto de la pregunta).

## `workflow_invoice_field_missing_reference`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: la referencia (factura u otro id) no resolvió a un número en el contexto.

## `workflow_invoice_field_missing_type`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: falta el tipo de campo personalizado.

## `workflow_invoice_field_missing_value_path`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: falta de dónde sacar la respuesta (`value_path`).

## `workflow_invoice_field_reserved`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: la pregunta es `tipo_de_compra` (Tipo de compra), que es del sistema y solo se elige al crear o editar la orden.
- **Qué hacer:** Cambiar `question_key` (o el nombre) del paso `crm.set_invoice_custom_field`.

## `workflow_invoice_field_unknown_type`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Campo de factura: el tipo de campo no existe.

## `workflow_invoke_depth_exceeded`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** La cadena de workflows que se invocan unos a otros llegó al máximo permitido.

## `workflow_invoke_self`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Un workflow no puede invocarse a sí mismo

## `workflow_invoke_target_invalid`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Workflow destino inválido

## `workflow_invoke_target_not_available`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El workflow destino no está disponible para invocación

## `workflow_loop_body_fell_through`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El cuerpo de un flow.for_each (_item) terminó en `end` sin volver al bucle (falta loop_return en el final de cada hoja alcanzable)

## `workflow_loop_invalid_item_key`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Bucle: un ítem de la colección no tiene el campo que lo identifica.

## `workflow_loop_invalid_source`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Bucle: la fuente no es una lista (¿el paso anterior no la dejó en el contexto?).

## `workflow_loop_max_iterations_reached`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Bucle: se alcanzó el máximo de vueltas.

## `workflow_loop_missing_branch`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Bucle: al correr faltan las ramas `_item` / `_done`.

## `workflow_return_point_not_found`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** «Volver» apunta a un punto de regreso que ya no existe en el workflow.

## `workflow_web_page_missing_branch`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Esperar resultado de la página web: faltan ramas obligatorias al correr.

## `workflow_web_page_no_session`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** Esperar resultado de la pagina web: antes hay que mandar la pagina web ("Enviar pagina web") en este flujo.

## `zombie_running_no_heartbeat`

- **Tipo:** workflow · **HTTP:** — · **Estado:** vigente
- **Qué significa:** El janitor cerró una ejecución que llevaba `running` demasiado tiempo sin latido (zombie). Una ejecución zombie bloquea el dedup de su trigger.
- **Causa típica:** El proceso murió a mitad de la ejecución (deploy, reinicio) o una action se colgó.
- **Cómo detectarlo:** Base: `workflow_execution_logs` con este `cause`.
- **Qué hacer:** Revisar qué paso estaba corriendo; si fue un deploy, no hay nada que arreglar.
