DEV Community

Pirate Prentice
Pirate Prentice

Posted on

n8n Error Trigger Node: Build a Global Error Handler for Your Workflows [Free JSON]

n8n Error Trigger Node: Build a Global Error Handler for Your Workflows [Free JSON]

Every workflow fails eventually. The Error Trigger node is n8n's global safety net: it fires automatically whenever another workflow crashes, giving you structured error data you can route to Slack, email, a log sheet, or a retry queue.

This guide covers the full Error Trigger setup, the data it provides, four practical patterns, a gotchas table, and a free copy-paste workflow JSON.


What the Error Trigger Node Does

The Error Trigger is a special trigger that starts a dedicated error-handler workflow whenever any workflow in your n8n instance throws an unhandled error.

Key facts:

  • It only works as the first node of a workflow designated as an error handler.
  • You assign the error handler in Settings → Error Workflow of the workflow you want to monitor.
  • One error handler workflow can serve multiple source workflows.
  • It receives rich context: the error message, the failed execution ID, and the full workflow metadata.

Setup: Three Steps

Step 1 — Create the error handler workflow

  1. Create a new workflow.
  2. Add an Error Trigger node as the first node.
  3. Build your alert/log logic after it (see patterns below).
  4. Activate the workflow.

Step 2 — Assign it to a source workflow

Open the workflow you want to monitor:

  1. Go to Settings (bottom-left gear icon).
  2. Set Error Workflow to the name of your error handler workflow.
  3. Save.

Now whenever that workflow fails, n8n triggers your error handler.

Step 3 — Test it

Create a temporary workflow with a single Code node that throws:

throw new Error('Test error from n8n');
Enter fullscreen mode Exit fullscreen mode

Assign your error handler, activate the test workflow, and execute it manually. Your error handler should fire within seconds.


The Error Trigger Output: What Data You Get

The Error Trigger provides a single item with this structure:

{
  "execution": {
    "id": "1234",
    "url": "https://your-n8n-instance/workflow/42/executions/1234",
    "retryOf": null,
    "error": {
      "message": "Cannot read properties of undefined",
      "stack": "TypeError: Cannot read...",
      "name": "TypeError"
    },
    "lastNodeExecuted": "HTTP Request",
    "mode": "trigger"
  },
  "workflow": {
    "id": "42",
    "name": "My Production Workflow"
  }
}
Enter fullscreen mode Exit fullscreen mode

Key fields you'll use in expressions:

Field Expression Description
Error message {{ $json.execution.error.message }} Human-readable error text
Failed node {{ $json.execution.lastNodeExecuted }} Which node crashed
Execution URL {{ $json.execution.url }} Direct link to the failed run
Workflow name {{ $json.workflow.name }} Which workflow failed
Workflow ID {{ $json.workflow.id }} Useful for routing logic

Pattern 1: Slack Alert on Failure

The most common pattern — sends an instant Slack message whenever a workflow fails.

Nodes: Error Trigger → Slack (Send Message)

Slack message template:

*Workflow failed:* {{ $json.workflow.name }}
*Error:* {{ $json.execution.error.message }}
*Node:* {{ $json.execution.lastNodeExecuted }}
*Link:* {{ $json.execution.url }}
Enter fullscreen mode Exit fullscreen mode

Tip: Use a dedicated #n8n-errors channel so alerts don't get lost. Set the Slack node to only notify on unique error messages (check the dedup pattern in Pattern 4) to avoid alert fatigue.


Pattern 2: Log Errors to Google Sheets or Postgres

For compliance or trend analysis, log every failure to a persistent store.

Nodes: Error Trigger → Google Sheets (Append Row) or Postgres (Insert)

Columns to capture:

Column Expression
timestamp {{ $now.toISO() }}
workflow_name {{ $json.workflow.name }}
workflow_id {{ $json.workflow.id }}
error_message {{ $json.execution.error.message }}
last_node {{ $json.execution.lastNodeExecuted }}
execution_url {{ $json.execution.url }}
resolved false

Add a resolved column you manually update — gives you an easy filter for open issues.


Pattern 3: Auto-Retry with Backoff

For transient errors (API timeouts, rate limits), automatically retry the failed execution.

Nodes: Error Trigger → IF (check error type) → n8n (Retry Execution via HTTP Request)

IF: {{ $json.execution.error.message.includes('timeout') || $json.execution.error.message.includes('rate limit') }}
→ true: HTTP Request → POST /api/v1/executions/{{ $json.execution.id }}/retry
→ false: Slack alert (non-retryable error)
Enter fullscreen mode Exit fullscreen mode

Gotcha: The retry API endpoint requires an n8n API key. Store it as an n8n credential and inject via the HTTP Request node's Header Auth. Do not hardcode it in expressions.


Pattern 4: Error Triage — Route by Severity

Route errors to different channels based on severity, workflow type, or error message content.

Nodes: Error Trigger → Switch → [Critical channel / Warning channel / Log only]

Example routing rules:

Rule 1 (Critical): workflow.name contains "payment" OR "invoice"
  → PagerDuty + Slack #critical

Rule 2 (Warning): error.message contains "timeout" OR "rate limit"
  → Slack #warnings (retryable, low urgency)

Rule 3 (Default): everything else
  → Append to Google Sheets log only
Enter fullscreen mode Exit fullscreen mode

This prevents alert fatigue while ensuring real outages get immediate attention.


Gotchas Table

Gotcha What happens Fix
Error handler itself fails Silent failure — no nested error loop Keep error handler simple; test it separately
Workflow not activated Error Trigger never fires The error handler workflow must be active
Error Workflow not assigned Source workflow failure goes unhandled Set Settings → Error Workflow on every production workflow
Execution URL is localhost URL points to internal host Set N8N_EDITOR_BASE_URL env var to your public domain
Missing retryOf field Null on first failure Check for null before using in retry logic
Infinite retry loop Retried execution fails → triggers error handler → retries again Add a retryOf check: only retry if $json.execution.retryOf == null

Free Workflow JSON: Error Alert + Log

This workflow sends a Slack message and appends a row to Google Sheets on every failure. Replace the Slack channel ID and Sheets spreadsheet ID with your own values.

{
  "name": "op: Global Error Handler",
  "nodes": [
    {
      "parameters": {},
      "id": "error-trigger-1",
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "typeVersion": 1,
      "position": [240, 300]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": { "value": "YOUR_SLACK_CHANNEL_ID" },
        "text": "=*Workflow failed:* {{ $json.workflow.name }}\n*Error:* {{ $json.execution.error.message }}\n*Node:* {{ $json.execution.lastNodeExecuted }}\n*Link:* {{ $json.execution.url }}",
        "otherOptions": {}
      },
      "id": "slack-alert-1",
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [480, 200]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": { "value": "YOUR_SPREADSHEET_ID" },
        "sheetName": { "value": "Errors" },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {
            "timestamp": "={{ $now.toISO() }}",
            "workflow": "={{ $json.workflow.name }}",
            "error": "={{ $json.execution.error.message }}",
            "node": "={{ $json.execution.lastNodeExecuted }}",
            "url": "={{ $json.execution.url }}",
            "resolved": false
          }
        }
      },
      "id": "sheets-log-1",
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [480, 420]
    }
  ],
  "connections": {
    "Error Trigger": {
      "main": [[
        { "node": "Slack Alert", "type": "main", "index": 0 },
        { "node": "Log to Sheets", "type": "main", "index": 0 }
      ]]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Import this via n8n menu → Import from JSON. Assign it as the Error Workflow in Settings on each production workflow you want to monitor.


Summary

Task How
Create error handler New workflow → Error Trigger as first node → Activate
Assign to a workflow Source workflow Settings → Error Workflow
Get error message $json.execution.error.message
Get failed node $json.execution.lastNodeExecuted
Get execution link $json.execution.url
Avoid infinite retry Check $json.execution.retryOf == null first

The Error Trigger is one of the highest-leverage nodes you can add to a production n8n setup — a single error handler workflow covers every workflow you assign it to, and it costs nothing to run.


Want more production-ready n8n patterns? The n8n Workflow Starter Pack includes 10 pre-built, documented workflow JSONs — webhook ingestion, error handling, Stripe payment events, data transformation, and more. One-time purchase, import and use.

Top comments (1)

Collapse
 
pirateprentice profile image
Pirate Prentice

Quick question for anyone using the Error Trigger in production: are you routing all workflow errors to one global handler, or do you prefer per-workflow error branches?

I've seen teams start with global (simpler to set up) then migrate to per-workflow error handling once they need different retry logic per workflow type. Curious what's working for others.