Skip to content
Agentmart
Submit a tool

n8n-error-handling

Wire n8n error handling so failures are loud, structured, and recoverable.

Skill by czlonkowski

IndexedMIT★ 6,517
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/czlonkowski-n8n-error-handling

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Wire n8n error handling so failures are loud, structured, and recoverable. Use when building any webhook/API workflow, a scheduled or unattended workflow, or any path where a silent failure would drop user-visible work — and whenever the user mentions error handling, onError, continueErrorOutput, error branches/outputs, retries, retryOnFail, Respond to Webhook status codes, 4xx/5xx, Error Trigger, or "my workflow fails silently". Covers per-node error outputs and wiring, retry/self-healing, error-trigger workflows, and 4xx/5xx response shapes.

Use cases: backend, productivity, debugging, workflow-automation

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/n8n-error-handling

What's inside

Skill name
n8n-error-handling
Description
Wire n8n error handling so failures are loud, structured, and recoverable. Use when building any webhook/API workflow, a scheduled or unattended workflow, or any path where a silent failure would drop user-visible work — and whenever the user mentions error handling, onError, continueErrorOutput, error branches/outputs, retries, retryOnFail, Respond to Webhook status codes, 4xx/5xx, Error Trigger, or "my workflow fails silently". Covers per-node error outputs and wiring, retry/self-healing, error-trigger workflows, and 4xx/5xx response shapes.
License
MIT
Instructions
281 lines in SKILL.md · view on GitHub

Files (6)

  • API_WORKFLOWS.md
  • ERROR_WORKFLOWS.md
  • NODE_ERROR_OUTPUTS.md
  • README.md
  • RESPONSE_SHAPES.md
  • SKILL.md

SKILL.md (first lines)

# n8n Error Handling

By default, when an n8n node throws, the **whole workflow halts**. For an interactive run you're watching, that's fine — you see the red node and fix it. For anything unattended (a webhook API, a cron job, a queue worker, an agent tool), it's the wrong default: the caller gets a timeout or an empty 500, the operator gets no alert, and the symptom is "the integration just stopped working" with no log and no clue.

This skill is about making failures **loud, structured, and recoverable** — and, best case, **self-healing** so transient blips never reach a human at all.

The two ideas that prevent most silent failures:

- **Per-node error outputs** — a node's failure routes down a second output you control, instead of killing the run.
- **A workflow-level error workflow** — a catch-all that fires for anything that escapes per-node handling (timeouts, crashes between nodes, unwired failures).

---

## When you actually need this

| Workflow shape | Error handling posture |
|---|---|
| Webhook / API (anything with `Respond to Webhook`) | **Required.** Every fallible node's error output wired; status code matches cause. |
| Scheduled / cron / queue worker / agent tool (unattended) | **Required.** A workflow-level error workflow, plus `retryOnFail` on network nodes. |
| Internal one-off you run and watch yourself | **Optional.** Default `onError: "stopWorkflow"` is fine — you'll see the red node and re-run. |

The dividing line: **if anyone other than you sees the output** — a downstream system, an end user, an on-call engineer — the failure has to be handled, not swallowed. If you're the only watcher and the cost of failure is "I notice and re-run", looser is fine.

---

## The #1 silent trap: per-node error output is a TWO-step setup

This is the single most common way an n8n workflow "handles" errors while actually swallowing them. Routing a node's failure to a handler takes **two** changes, and doing only one looks complete but misbehaves:

1. **Set `onError: "continueErrorOutput"`** on the node. This is what *creates* the second output. Without it, `main[1]` doesn't exist no matter what you wire.
2. **Wire that error output** (`connections.<node>.main[1]`, i.e. `sourceIndex: 1`) to a real handler. Without a target, the error data is emitted into the void.

Get one without the other and you hit a failure mode:

| What you did | What happens at runtime |
|---|---|
| `onError` set, error output **not** wired | Error data is silently discarded. Downstream doesn't fire. The dashboard shows the run as **succeeded**. Worst case — no error logged anywhere. |
| Error output wired, `onError` **not** set | The slot never fires; the handler is unreachable. On failure the workflow just **halts** (default `stopWorkflow`). |
| Both done | Failure routes down `main[1]` to your handler. ✅ |

### Doing both with `n8n_update_partial_workflow`

```javascript
// 1) Turn on the error output (creates main[1])
{ type: "updateNode", nodeName: "HTTP Request",
  changes: { onError: "continueErrorOutput" } }

// 2) Wire the error output to a handler. sourceIndex: 1 = the error output.
{ type: "addConnection",
  source: "HTTP Request",
  target: "Handle Error",
  sourceIndex: 1 }
```

`sourceIndex: 0` is the success path, `sourceIndex: 1` is the error path. (For IF nodes the aliases `branch: "true"`/`"false"` map to index 0/1; for a generic fallible node, use the explicit `sourceIndex: 1`.)

**Then verify.** This trap doesn't surface in `validate_workflow` — a half-wired error output validates clean. Pull the workflow with `n8n_get_workflow` and confirm **both** halves:

- The node's `onError` is `"continueErrorOutput"`.
- `connections["HTTP Request"].main[1]` contains your handler.

Valid `onError` values:

| Value | Effect |
|---|---|
| `"stopWorkflow"` (default) | Error halts the whole workflow. |
| `"continueRegularOutput"` | Error item flows out the **normal** output. Rare, usually wrong — downstream gets error-shaped data and keeps going. |
| `"continueErrorOutput"` | Error item flows out the **separate** error output (`main[1]`). The one you wire. |

Full failure-mode catalog, fan-in/fan-out shapes, and verification: **NODE_ERROR_OUTPUTS.md**.

### Failures the error output never sees

A correctly wired error output still misses whole classes of failure. Verified on n8n 2.38.5:

| Failure | With `continueErrorOutput` | With `continueRegularOutput` |
|---|---|---|
| JS error **inside `{{ }}`** (TypeError on a missing path, `JSON.parse` on bad input, a thrown `Error`, a JMESPath syntax error) | nothing fires; the field is `null` and items take the **success** path | same |
| Python Code node **rejected before running** (blocked import, dunder access: `Security violations detected`) or **bad return shape** (list in each-item mode) | node marked failed, but the **unchanged input items leave through the success output**; `main[1]` stays empty and the execution shows success | unchanged input items pass through |
| Exception **while** code runs (`raise`/`throw`, `KeyError`, `NameError`) | routed to `main[1]` as `{ error }` ✅ | `{ error }` item on the main output |

So an error branch alone can't guard these:

- **Guard the data, not just the node.** After a transform whose output matters, check that the
  field you produced exists (IF/Filter on `{{ $json.total !== undefined && $json.total !== null }}`)
  and send the miss down the error path yourself.
- **Test-run and read node statuses and output values.** The Python cases show a red node inside a
  green execution. The expression cases show nothing but `null`s.
- Root causes and fixes: **n8n-expression-syntax** (Debugging) and **n8n-code-python** (Errors and `onError`).

---

## Self-healing first: `retryOnFail` before you wire error paths

Before you build error branches, absorb the transient failures so they never reach those branches. On **any node that calls a network service** — HTTP Request, comms (Gmail/Slack/Discord), databases, AI nodes, third-party integrations — set node-level retry:

```javascript
{ type: "updateNode", nodeName: "HTTP Request",
  changes: {
    retryOnFail: true,
    maxTries: 3,
    waitBetweenTries: 5000   // ms
  } }
```

Why this comes **first**: a 429 or a brief upstream hiccup will retry and usually succeed on its own. The error output then fires only on *real, persistent* failures — so your 5xx responses and on-call alerts reflect actual problems instead of noise.

Engine limits to know: retry fires on **any** error (there's no per-status-code filter), `maxTries` caps at 5, and `waitBetweenTries` caps at 5000ms — so 5000 is both the max and a sensible default. See **n8n-node-configuration** (NODE_FAMILY_GOTCHAS.md) for node-specific notes.

---

## API workflows: the canonical shape

A webhook-triggered workflow that responds to its caller has one rule that overrides everything else: **no hanging branches**. Every path — success and every error — must end at a `Respond to Webhook`, or the caller sits there until it times out.

```
Webhook (responseMode: "responseNode")
  ├── validate input → process → Respond (200, body)
  └── (any fallible node's error output → sourceIndex 1)

From czlonkowski/n8n-skills, MIT.

More from czlonkowski/n8n-skills

Signals

Stars
6,517
Forks
1,075
Open issues
10
Last commit (this folder)
Oct 24, 2026 (4 days ago)
Last release
Oct 24, 2026 (4 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from czlonkowski

Cite this page

n8n-error-handling skill. Agent Mart. https://agentmart.dev/skills/czlonkowski-n8n-error-handling (last updated 2026-10-24)