# Make n8n workflows fail loudly and recover predictably
Use this when a workflow must survive failures unattended: scheduled jobs, webhook
APIs, queue workers. Default n8n behavior on any node error is to halt the whole
workflow, and the caller or the schedule gets nothing useful. Pick the mechanism
by classifying the failure scenario FIRST — the three mechanisms compose, and
picking the wrong one is how you get silent data corruption or alert storms.
## 1. Classify the scenario
- **A specific node can fail in a predictable way and you want to branch on it**
(HTTP 404 means "not found, skip"; 500 means "retry later"). Use the node
Settings tab → **On Error**.
- **A specific node fails transiently** (429 rate limits, upstream blips, brief
network drops) and would succeed if retried. Use node Settings tab → **Retry
On Fail**.
- **Anything unexpected can fail anywhere** (timeouts, crashes between nodes, a
node you forgot to wire) and someone must be told. Use a workflow-level
**error workflow**: a separate workflow whose first node is the **Error Trigger**
node, assigned in the main workflow's Settings → "Error workflow".
These are not alternatives: network nodes get Retry On Fail AND the workflow gets
an error workflow. Retry absorbs the blip; the error workflow catches what retry
can't.
## 2. On Error: the three settings mean very different things
In node Settings → On Error:
- **Stop Workflow** (default): halts the entire workflow on error. Safe, loud —
but for a webhook API the caller hangs or gets nothing unless the workflow
also wires a response.
- **Continue**: proceeds to the next node despite the error, using the last valid
data. Dangerous for fallible nodes: downstream nodes silently process stale or
empty data as if it were the real result. Use it only when "no data" is
genuinely equivalent to "skip", e.g. an optional lookup.
- **Continue (using error output)**: continues, but passes the error information
to the next node so you can branch on it. This is the predictable-failure
handler: wire the error output to an IF/Switch that distinguishes error types
(e.g. 404 → skip, 500 → alert) and make sure both branches end somewhere sane —
for a webhook API, both paths must reach a Respond to Webhook node, or the
caller times out on the error path.
**Always Output Data** is a related trap: the node emits an empty item even when
it produced nothing. On an IF node this can create an infinite loop — set it only
deliberately, never as a debugging band-aid.
## 3. Retry On Fail: transient failures only
Enable it on nodes that call the network (HTTP Request, third-party API nodes,
database nodes). It reruns the node up to the configured Max Tries with a wait
between tries. Two rules:
- It does not change the On Error behavior: if all tries fail, the On Error
setting (or the error workflow) still decides what happens.
- Do not put Retry On Fail on nodes with side effects that are not idempotent
(sending email, charging a card) unless the node or API deduplicates — a retry
after a timeout can execute the side effect twice, because the first attempt
may have succeeded without its response reaching n8n.
## 4. Error workflow: the global safety net
1. Create a new workflow: Error Trigger node → format the alert (Set node) →
notify (Slack/email/PagerDuty). The trigger must be the first node, and the
error workflow itself must be **active** — an inactive error workflow never
runs, and failures stay silent.
2. In the main workflow: Settings → "Error workflow" → select it. Save.
What the Error Trigger payload contains, and what it does not:
- It **does** contain: the error message (`$json.execution.error.message`), the
workflow name, the execution id and URL, the failed node's name
(`$json.execution.lastNodeExecuted`), and the execution mode. Enough to page
someone with "which workflow, which node, what error".
- It does **not** contain the input data that caused the failure. If triage needs
the offending payload, add an n8n node (operation: get execution, include
execution details) keyed on the execution id, using a personal access token
created under Settings → API attached to the node's credential. Without it the
node fails with a 401 — an unhandled error inside the error workflow itself.
Keep the error workflow simple: every node in it is one more thing that can fail
without anyone noticing.
## 5. Checklist
1. List the fallible nodes (HTTP, DB, file, third-party). Transient ones get
Retry On Fail; predictable ones get Continue (using error output) with a wired
error branch.
2. Set a workflow-level error workflow for everything else; verify it is active.
3. Verify the Error Trigger payload has what your alert needs; add the get
execution step only if you need the offending input data.
4. Test the failure paths, not just the happy path: force a 500, force a timeout,
confirm the caller gets a response and the alert fires.
5. Never use Continue on a node whose downstream would mistake stale/empty data
for a real result.