Error handling and the error workflow
Every workflow touching external systems will fail at some point. The question is not whether it fails but who learns about it, and when.
Error handling in n8n is built at three levels:
- Node level — retries, and how the node behaves when it errors
- Workflow level — an error workflow set in Workflow Settings
- Logical level — failing an execution deliberately on your own condition with the Stop And Error node
An error workflow is a separate workflow that must start with the Error Trigger node. It runs when the main workflow's execution fails. One error workflow can serve many workflows — which is exactly how centralised alerting is built in practice.
[
{
"execution": {
"id": "231",
"url": "https://n8n.example.com/execution/231",
"retryOf": "34",
"error": {
"message": "Example Error Message",
"stack": "Stacktrace"
},
"lastNodeExecuted": "Node With Error",
"mode": "manual"
},
"workflow": {
"id": "1",
"name": "Example Workflow"
}
}
]The default payload the Error Trigger receives. `execution.id` and `execution.url` require the execution to be saved in the database; `retryOf` appears only on retries.
An important nuance: if the failure happened in the main workflow's trigger node, the payload reaching the error workflow is different — execution{} carries less and a trigger{} object appears instead. The reason is simple: the workflow never really executed.
Keep that in mind when writing an error workflow: assuming execution.url is always present is a mistake.
Retrying does not suit every error. Treat it as meaningful only for transient failures:
429,5xx, network errors, timeouts → retrying makes sense400,401,403,404→ retrying is pointless; the request, the credential or the resource is wrong
Sending a bad request three times does not fix it — it only delays the moment the failure becomes visible.
| Situation | The right behaviour |
|---|---|
| 3 of 100 records fail | Continue-on-error at node level — route failures down a separate path and report at the end |
| The API is temporarily unavailable | Node-level retry with an interval between attempts |
| The credential has expired | Do not retry — alert immediately; this needs a person |
| The incoming data is not in the expected shape | Validate early with an IF; stop with a clear message using Stop And Error |
| The whole process has stopped | Immediate alert from the error workflow: which workflow, which node, the execution link |
Silent failure is the worst outcome. The workflow breaks, nobody knows, and two weeks later somebody asks "why is this data stale?". So setting an error workflow on every production workflow is the minimum bar — build it once and attach it everywhere.
📚 Sources and documentation
- Handle errors gracefullyofficialdocs.n8n.io
The official structure of the Error Trigger payload is here.
- Error Trigger nodeofficialdocs.n8n.io
- Stop And Error nodeofficialdocs.n8n.io
- Configure workflow settingsofficialdocs.n8n.io
This is where the error workflow is assigned.