name: n8n-error-handling description: Error handling patterns for n8n workflows including error workflows, Error Trigger, Stop And Error, Continue On Fail, retry logic, and production error monitoring. Use when implementing error handling, building error workflows, debugging failed executions, or setting up alerting.
n8n Error Handling — Complete Reference
Production-grade error handling patterns for n8n workflows.
Source: https://docs.n8n.io/flow-logic/error-handling/
1. Error Handling Overview
Error Handling Mechanisms
| Mechanism | Scope | Purpose |
|---|---|---|
| Error Workflow | Workflow-level | Runs separate workflow on failure |
| Error Trigger | Node in error workflow | Receives error data |
| Stop And Error | Node in main workflow | Force deliberate failure |
| Continue On Fail | Per-node setting | Prevent node from stopping workflow |
| Retry On Fail | Per-node setting | Auto-retry failed node |
| Always Output Data | Per-node setting | Output data even on failure |
| Try/Catch in Code | Code node | Handle errors in custom code |
2. Error Workflows
Creating an Error Workflow
Step 1: Create a new workflow with Error Trigger as first node:
Error Trigger → Set (format error) → Slack/Email (send alert)
Step 2: Configure alert message:
// In Set node, format the error notification
{
"errorMessage": "={{$json.execution.error.message}}",
"workflowName": "={{$json.workflow.name}}",
"executionId": "={{$json.execution.id}}",
"executionUrl": "={{$json.execution.url}}",
"failedNode": "={{$json.execution.lastNodeExecuted}}",
"mode": "={{$json.execution.mode}}",
"timestamp": "={{$now.toISO()}}"
}
Step 3: Assign to main workflow:
- Main workflow → Options → Settings
- Error workflow → select your error handler
- Save
Error Trigger Data Structure
Standard execution error:
[
{
"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"
}
}
]
Trigger node activation error (different structure):
{
"trigger": {
"error": {
"context": {},
"name": "WorkflowActivationError",
"cause": {
"message": "Connection refused",
"stack": "Error: connect ECONNREFUSED..."
},
"timestamp": 1654609328787,
"message": "Workflow could not be activated",
"node": {
"name": "Webhook",
"type": "n8n-nodes-base.webhook"
}
},
"mode": "trigger"
},
"workflow": {
"id": "5",
"name": "My Webhook Workflow"
}
}
Error Data Fields
| Field | Available | Description |
|---|---|---|
execution.id | When saved to DB | Execution identifier |
execution.url | When saved to DB | Direct link to execution |
execution.retryOf | On retries only | ID of original failed execution |
execution.error.message | Always | Human-readable error |
execution.error.stack | Always | Stack trace |
execution.lastNodeExecuted | Always | Node that failed |
execution.mode | Always | manual, trigger, webhook |
workflow.id | Always | Workflow identifier |
workflow.name | Always | Workflow name |
3. Stop And Error Node
Purpose
Force a workflow to fail deliberately under your conditions. This triggers the error workflow.
Use Cases
- Validation failures: Missing required data
- Business rule violations: Invalid amounts, unauthorized access
- Threshold exceeded: Rate limits, quotas
- Data integrity checks: Mismatched records
Configuration
{
"errorType": "message", // "message" or "object"
"message": "Validation failed: email is required"
}
Pattern: Validation → Stop And Error
Webhook → IF (email exists?)
→ [Yes] → Continue processing
→ [No] → Stop And Error ("Missing email")
→ triggers Error Workflow
Trigger → Code (validate) → IF (valid?)
→ [Yes] → Process
→ [No] → Stop And Error
4. Per-Node Error Settings
Continue On Fail
Location: Node Settings → On Error → Continue On Fail
What it does: Node errors don't stop the workflow. Error data is passed as output.
Error output format:
[
{
"json": {
"error": {
"message": "404 Not Found",
"description": "The requested resource was not found"
}
}
}
]
Pattern: Handle errors inline
HTTP Request (Continue On Fail) → IF (has error?)
→ [Yes] → Log error → Fallback action
→ [No] → Process response
Retry On Fail
Location: Node Settings → On Error → Retry On Fail
Configuration:
- Max Retries: Number of retry attempts (1-5)
- Wait Between: Milliseconds between retries (0-5000)
Use for: Transient errors (network timeouts, rate limits, temporary unavailability).
Always Output Data
Location: Node Settings → Always Output Data
What it does: If a node returns no output data, it creates an empty item instead of stalling the workflow.
5. Code Node Error Handling
Try/Catch Pattern
try {
const response = await $helpers.httpRequest({
method: 'POST',
url: 'https://api.example.com/data',
body: { name: $json.body.name }
});
return [{
json: {
success: true,
data: response,
timestamp: new Date().toISOString()
}
}];
} catch (error) {
return [{
json: {
success: false,
error: error.message,
statusCode: error.statusCode || 500,
timestamp: new Date().toISOString()
}
}];
}
Validation with Explicit Errors
const items = $input.all();
if (!items || items.length === 0) {
throw new Error('No input data received');
}
const data = items[0].json;
if (!data.email) {
throw new Error('Missing required field: email');
}
if (!data.email.includes('@')) {
throw new Error(`Invalid email format: ${data.email}`);
}
// Continue processing...
return [{json: {validated: true, ...data}}];
Batch Error Handling
const items = $input.all();
const results = [];
const errors = [];
for (const item of items) {
try {
const processed = transformItem(item.json);
results.push({ json: { ...processed, status: 'success' } });
} catch (error) {
errors.push({
json: {
originalItem: item.json,
error: error.message,
status: 'failed'
}
});
}
}
// Return both successes and failures
return [...results, ...errors];
6. Production Error Handling Patterns
Pattern 1: Centralized Error Handler
Error Workflow:
Error Trigger
→ Set (format error data)
→ Switch (by severity)
→ [Critical] → PagerDuty + Slack #alerts
→ [Warning] → Slack #warnings
→ [Info] → Log to database
Pattern 2: Self-Healing Retry
Main Workflow:
Trigger → HTTP Request (Retry: 3, Wait: 2000ms, Continue On Fail)
→ IF (success?)
→ [Yes] → Process
→ [No] → Wait 30s → Execute Sub-workflow (same logic)
→ IF (still failed?)
→ [Yes] → Stop And Error
→ [No] → Process
Pattern 3: Dead Letter Queue
Main Workflow:
Trigger → Process (Continue On Fail)
→ IF (has error?)
→ [Yes] → Postgres (insert into dead_letter_queue)
→ Slack (notify about failed item)
→ [No] → Continue normal flow
Pattern 4: Circuit Breaker
// In Code node: Check error count before proceeding
const errorCount = $node["Count Errors"].json.count || 0;
const threshold = 5;
if (errorCount >= threshold) {
// Circuit is OPEN - skip processing
return [{
json: {
circuitState: 'OPEN',
message: `Too many errors (${errorCount}). Skipping.`,
nextRetry: DateTime.now().plus({minutes: 15}).toISO()
}
}];
}
// Circuit is CLOSED - proceed normally
return [{json: {circuitState: 'CLOSED', proceed: true}}];
Pattern 5: Graceful Degradation
Trigger → HTTP Request Primary API (Continue On Fail)
→ IF (success?)
→ [Yes] → Use primary data
→ [No] → HTTP Request Fallback API (Continue On Fail)
→ IF (success?)
→ [Yes] → Use fallback data
→ [No] → Use cached/default data
7. Investigating Errors
Execution History
- Single workflow: Open workflow → Executions tab
- All workflows: Main menu → Executions
- Filter by: status (success/error), date range, workflow
Execution Debug Mode
- Open failed execution from Executions list
- Click "Debug" to load failed data into editor
- Modify and re-run from the failed node
Log Streaming (Enterprise)
Stream execution logs to external services:
- Sentry
- Datadog
- Custom HTTP endpoint
8. Error Handling Checklist
For Every Production Workflow
- Error workflow assigned in workflow settings
- Critical nodes have Continue On Fail or Retry On Fail
- API calls have retry logic (Retry: 3, Wait: 1000ms)
- Validation before processing (IF nodes or Code validation)
- Meaningful error messages in Stop And Error nodes
- Alert routing in error workflow (Slack/email/PagerDuty)
- Error context includes workflow name, execution ID, failed node
- Edge cases handled (empty data, null values, timeout)
Error Workflow Template
Error Trigger
→ Set Node:
errorMessage: ={{$json.execution.error.message}}
workflowName: ={{$json.workflow.name}}
executionId: ={{$json.execution.id}}
executionUrl: ={{$json.execution.url}}
failedNode: ={{$json.execution.lastNodeExecuted}}
timestamp: ={{$now.toISO()}}
→ Slack Node:
Channel: #workflow-errors
Text: |
🚨 Workflow Error
Workflow: {{$json.workflowName}}
Error: {{$json.errorMessage}}
Failed Node: {{$json.failedNode}}
Execution: {{$json.executionUrl}}
Time: {{$json.timestamp}}
Related Skills
- n8n-flow-logic — Error handling in context of flow control
- n8n-code-javascript — Try/catch in Code nodes
- n8n-workflow-patterns — Error handling in workflow patterns
- n8n-node-configuration — Configure error settings per node
Documentation Source: https://docs.n8n.io/flow-logic/error-handling/