📦 deps(thirdparty): update snapshots

This commit is contained in:
ci[bot]
2026-07-22 10:09:47 +00:00
parent 316c012df0
commit 60364c6660
353 changed files with 24740 additions and 1264 deletions
@@ -0,0 +1,171 @@
# Per-Node Error Outputs
This file is about the **error output on a single node** — the second `main` output that fires when that node throws — and the two-step setup that trips up nearly everyone. For the workflow-level catch-all (Error Trigger workflows) and the webhook/Respond shape, see the rest of `n8n-error-handling`.
The whole point: a node failing should route somewhere *you* control, instead of halting the run. The cost of forgetting half the setup is one of the worst silent-failure modes in n8n — a run that shows green while quietly dropping its work.
---
## The two-step setup (both are required)
Routing a node's failure takes exactly two changes. Either one alone looks finished and misbehaves.
### Step 1 — create the error output
Set `onError: "continueErrorOutput"` on the node. This is what *adds* the second output. Until you do, `main[1]` does not exist and nothing you wire to it can fire.
```javascript
{ type: "updateNode", nodeName: "Google Sheets",
changes: { onError: "continueErrorOutput" } }
```
Surgical alternative if you're touching only this field:
```javascript
{ type: "patchNodeField", nodeName: "Google Sheets",
fieldPath: "onError", value: "continueErrorOutput" }
```
The valid `onError` values:
| Value | Effect |
|---|---|
| `"stopWorkflow"` (default) | Error halts the whole workflow. The right default for runs you watch. |
| `"continueRegularOutput"` | The error item flows out the **normal** output (`main[0]`) alongside successes. Rare and usually a mistake — downstream gets error-shaped data and keeps going. |
| `"continueErrorOutput"` | The error item flows out a **separate** error output (`main[1]`). This is the one you wire below. |
### Step 2 — wire the error output
With `onError: "continueErrorOutput"`, the node has two outputs:
- `main[0]` → success path (`sourceIndex: 0`)
- `main[1]` → error path (`sourceIndex: 1`)
Wire the error output to a real handler:
```javascript
{ type: "addConnection",
source: "Google Sheets",
target: "Handle Error",
sourceIndex: 1 }
```
`sourceIndex: 1` is the error output. (IF nodes accept the friendly aliases `branch: "true"`/`branch: "false"` for index 0/1; a generic fallible node has no such alias — use the explicit `sourceIndex: 1`.)
---
## Failure modes — why "one of two" is so dangerous
### `onError` set, error output NOT wired
```javascript
// onError: "continueErrorOutput" set on the node,
// but no addConnection from sourceIndex 1.
```
On failure the node emits to `main[1]`, which has **no targets**. The error data is silently discarded, downstream never fires, and — this is the trap — the execution is recorded as **succeeded**, because from n8n's perspective the error was "handled" by a branch that happens to go nowhere. No failed execution logged, nothing in the dashboard. The integration "just stops working" and there's no trail.
**Fix:** wire `sourceIndex: 1` to a real handler, *or* set `onError` back to `"stopWorkflow"` so the failure is loud again.
### Error output wired, `onError` NOT set
```javascript
// addConnection from "Some Node" sourceIndex 1 → "Handle Error" exists,
// but the node still has the default onError: "stopWorkflow".
```
The connection sits in the JSON, but the slot it feeds from never fires. The handler is unreachable. On failure the workflow simply **halts** (default behavior). Less dangerous than the first mode — at least it's loud — but the handler you built does nothing.
**Fix:** set `onError: "continueErrorOutput"` on the node.
### Why validation won't save you
A half-wired error output **validates clean**. `validate_workflow` and `n8n_validate_workflow` don't flag "`onError` is set but `main[1]` is empty" or vice versa — both are structurally legal. This is a runtime behavior, not a schema violation. The only reliable check is to read the workflow back (see Verification below).
---
## Common wiring shapes
### Single fallible node → error handler
```javascript
// Node config: onError: "continueErrorOutput"
{ type: "addConnection", source: "HTTP Request", target: "Respond Error", sourceIndex: 1 }
```
### Success path fans out, error path goes elsewhere
```javascript
{ type: "addConnection", source: "HTTP Request", target: "Save Result", sourceIndex: 0 }
{ type: "addConnection", source: "HTTP Request", target: "Notify Slack", sourceIndex: 0 }
{ type: "addConnection", source: "HTTP Request", target: "Respond Error", sourceIndex: 1 }
```
### Multiple fallible nodes → one shared error handler (fan-in)
```javascript
// Each of these nodes needs onError: "continueErrorOutput" on its own config.
{ type: "addConnection", source: "Fetch User", target: "Respond Error", sourceIndex: 1 }
{ type: "addConnection", source: "Call External", target: "Respond Error", sourceIndex: 1 }
{ type: "addConnection", source: "Write Database", target: "Respond Error", sourceIndex: 1 }
```
Fan-in keeps the graph readable: one error responder, many sources. The handler can inspect which node failed (the error payload carries the failing node's name) to differentiate the response.
### Both log AND respond on the same failure
Wiring the error output to two targets composes without conflict — both receive the error data:
```javascript
{ type: "addConnection", source: "Call External", target: "Log Full Error", sourceIndex: 1 }
{ type: "addConnection", source: "Call External", target: "Respond Error", sourceIndex: 1 }
```
Useful when you want a sanitized response *and* a private full-detail log on the same failure. (Or chain them: error output → Log → Respond, so the log runs first.)
---
## What counts as "fallible"
Wire an error output on anything that can throw at runtime:
- Network calls — HTTP Request, third-party API nodes, databases.
- Auth failures — expired credential, rotated token.
- Schema mismatches — missing DB column, JSON parse failure.
- Rate limits — 429 from upstream (configure `retryOnFail` first so these self-heal).
- File/binary operations — missing path, permission denied (see **n8n-binary-and-data**).
- Code nodes that can throw.
Usually **not** worth an error output:
- Set / Edit Fields on already-validated data.
- IF / Switch with simple expressions — if those throw it's a bug to fix, not a path to catch.
- Pure transformations with no I/O.
When unsure, wire it. The cost is one connection; the cost of not wiring it is a silent halt.
---
## Verification (do this every time)
After any create/update, pull the workflow with `n8n_get_workflow` and check **both halves** on each fallible node:
1. **Node config**`onError` is `"continueErrorOutput"` (or whatever you intended).
2. **Connections**`connections["<node>"].main[1]` contains the expected handler(s).
If either half is missing, you have a silent-failure setup. Fix before activating.
`n8n_autofix_workflow` can repair some structural issues, but it won't infer that you *meant* to wire an error path — the intent to handle a given node's failure is yours to express. Treat the read-back as mandatory.
---
## When to use an error workflow instead
Per-node outputs handle the failure of *one node you remembered to wire*. They do **not** catch:
- Failures on nodes you forgot to wire.
- Crashes between nodes.
- Whole-workflow timeouts.
- Trigger failures.
For those, you need a workflow-level **error workflow** (Error Trigger node). And note the inverse: a per-node error output that's wired to a no-op which drops the data counts as "handled" — so it will *suppress* the error workflow. Only catch per-node when you're genuinely acting on the error. See **ERROR_WORKFLOWS.md**.