Skip to main content

Troubleshooting: a flow execution that failed

A published flow shows failed or completed_with_errors, or one node inside a run keeps throwing. This page walks you through reading the execution row, identifying the failing node class, and deciding what to fix. For the field-by-field reference, see Flow Executions.

What an execution row tells you

The list row and the single-execution detail each carry a diagnosis surface:
  • status — which terminal (or in-flight) state the run reached. The run-level status values are running, waiting, completed, completed_with_errors, failed, and timeout. completed_with_errors and failed are the two failure modes this page covers.
  • error — the last failure message on the run. The convention is Last failed node <node_id>: <message> — the node id prefix tells you where to look, and the message tells you what went wrong.
  • steps — one entry per node that ran, in execution order. Each step carries node_id, node_type, a per-step status (completed, running, failed, skipped, or pending), plus the recorded input, output, and per-step error. Read the failing step’s input — that is usually where the answer is.
A per-step status of pending or running is not a failure — it means the run is parked (a delay node, a send-time schedule) or in progress.

Common node classes that fail

Node failures cluster into six classes. Match the error prefix/message to one: A run can also fail at the level guardrails: the run aborts if the flow isn’t published, if it has no nodes/edges (has no definition), exceeds the 300s wall-clock (timeout), or runs more steps than the cap (exceeded maximum of ... steps — possible runaway flow). Those are definition-level problems, not node problems.

Cross-reference the failed node with the flow definition

The trace gives you the node_id and node_type of the failing step. Open the flow (Flows → open flow → the editor) and find the node whose id matches the step’s node_id. The node_type (sendSms, sendWhatsapp, sendEmail, webhook, condition, aiAnalyze, aiClassifyIntent, etc.) tells you which node class the error belongs to, and the step input shows the resolved values the node actually received — compare them against the node’s configured fields.

Retry vs. fix

Some failures are retry-safe and some are not. Decide by class:
  • Retry is useless when the gate is deterministic — compliance opt-outs, a paused/invalid sender pool with no eligible senders, a template that never got Meta approval, or a malformed recipient field. A retry re-runs the same gate and fails the same way. Fix the gate first; the queue-side equivalents (quiet hours, sender-pool exhaustion, compliance gates) are the message stuck in queued page.
  • Retry is reasonable for upstream flakiness — a webhook endpoint that 503’d once, an AI analysis endpoint that timed out, a provider outage. Fix the upstream and re-run, or accept completed_with_errors when the error edge handled it.

When to export the trace for support

Escalate to support when:
  • The same flow keeps failing on the same node after the obvious fix (you corrected the input, the sender pool, the channel) and it still returns the same error.
  • A run reports timeout or exceeded maximum of ... steps and the flow looks well-formed.
  • The flow_name row shows "Untitled flow" (deleted flow) but executions keep arriving.
Export the trace for context: copy the full single-execution JSON from GET /api/v1/flows/executions/:id — the steps array, error, and trigger_data — and include your tenant id (Settings → Organization) and the execution id. That pair lets support pull the executor-side trace without a back-and-forth.

Error examples: what the strings mean

The strings in error are the node’s own failure message, verbatim. A short decode table:

See also