NodeRecipe.

n8n Error Handling: What 2,030 Published Workflows Actually Declare

We parsed 2,030 unique n8n workflow files. 84.8% declare no error handling of any kind, 4.4% swallow errors instead of handling them, and only 0.9% have an Error Trigger.

By Ali Ilyas · · Updated September 13, 2026

Most advice about n8n error handling is written from experience, which is fine, but nobody has said how common the problem actually is. So we counted.

This page reports what 2,030 unique published n8n workflow files declare at the node level: how many set a retry, how many route failures anywhere, how many quietly discard them. The headline is that 84.8% declare no error-handling field of any kind, and a further 4.4% set a field that throws the error away.

Everything below is reproducible from a public dataset in about five minutes, and the section on what that dataset can and cannot tell you is not boilerplate. It changes which of these numbers you should believe.

What's on this page

84.8% declare no error handling at all

The source is Zie619/n8n-workflows: MIT licensed, 2,061 workflow JSON files, cloned 12 September 2026. After removing exact duplicates that leaves 2,030 unique workflows, which is the denominator for everything here.

signalworkflowsshare
No error-handling field of any kind1,72184.8%
No retry, no error output, no Error Trigger1,81089.2%
onError: continueErrorOutput on at least one node1216.0%
retryOnFail: true on at least one node1085.3%
onError: continueRegularOutput1004.9%
continueOnFail: true (legacy)432.1%
Contains an Error Trigger180.9%

The Error Trigger row is the one that surprised us. It is the mechanism n8n gives you for catching a failed execution across a whole workflow, it takes about a minute to wire up, and eighteen workflows out of two thousand have one.

These are not toy files. Median workflow size is 12 nodes and the largest is 246, or 9 and 174 if you discount sticky notes, which make up 23% of all nodes and do nothing at runtime. A nine-node workflow with an HTTP call in the middle of it has somewhere to fail.

The 4.4% that look handled and aren't

Separating handling from suppression leaves a group worth naming: 89 workflows (4.4%) set only continueRegularOutput or continueOnFail, and nothing else.

Both of those mean the same thing in practice. When the node fails, the failure is passed along the normal output as a data item and the workflow keeps running. Nothing retries. Nothing branches. The execution is very likely marked successful.

That is worse than declaring nothing at all. A workflow with no error handling fails loudly and you find out. A workflow that suppresses errors and carries on writes partial data, reports success, and tells you nothing. And because someone did type something into the error-handling field, it reads as deliberate to the next person who opens it.

If you use continueRegularOutput, the thing that makes it real is checking the error field on the branch afterwards. We have no data on how many do, because that check lives in node parameters we did not try to parse reliably across every node type.

Append or Update: 69 of 71 use it as an identity key

This is the part we went looking for, and the reason is worth stating. In September 2026 an automation consultant, Hayrullah Kar, read our Google Sheets integration guide and pointed out that our description of Append or Update was wrong in a specific way: we called the matching column an identity key, and it cannot be one. The operation reads the sheet to find a matching row, then writes. The Sheets API has no conditional write that would collapse those into a single step, so two executions carrying the same key can both look, both find nothing, and both append.

We fixed the article. The open question was how common the pattern is, and now there is an answer.

Across the corpus there are 595 Google Sheets nodes in 279 workflows. The operations break down as append 183, update 125, appendOrUpdate 70, upsert 1, other 14, unset 202.

That gives 71 Append-or-Update nodes across 53 workflows. Of those 71 nodes, 69 specify a matching column, which is to say that 69 of 71 use the operation exactly as an identity key. The columns chosen are what you would expect: id (8), Email (5), Id (4), xid (3), email (3), ID (3), place_id (2).

Now look at those 53 workflows:

countshare
No retry, no error output, no Error Trigger4381.1%
retryOnFail anywhere in the workflow611.3%
retryOnFail on the upsert node itself35.7%
onError: continueErrorOutput anywhere611.3%
Contains an Error Trigger00%
Error suppression present815.1%

Forty of the 53 have an automatic trigger (schedule 28, Google Sheets 10, webhook 6, Gmail 4, form 3, Drive 2), meaning they can fire without anyone watching, which is the precondition for two executions overlapping. Thirty-one of those 40 have no error handling of any kind.

Three workflows in the corpus put a retry on the node doing the upsert. None has an Error Trigger.

To be careful about what this shows: a retry does not fix a non-atomic read-then-write, and neither does an Error Trigger. Under concurrency they can make duplicates more likely, not less. The number is evidence about attention, not about correctness. 81% of the workflows using the riskiest Sheets operation have not thought about failure at any level.

What to change in your own workflows

Four things, in the order they pay off.

Add an Error Trigger workflow. One workflow, one Error Trigger node, one notification node pointed at wherever you actually read messages. Set it as the error workflow on everything else. This is the 0.9% row above, it takes a minute, and it converts silent failure into a message.

Put retryOnFail on reads that cross the network. HTTP GETs, lookups, anything that fetches. The default of not retrying means one timeout kills the run. Two or three tries with a wait of a few seconds absorbs the ordinary case, and the most common waitBetweenTries value in the corpus is 5000ms, which is a reasonable place to start.

Be careful retrying writes. A retry is safe when the operation is safe to repeat, and a write usually isn't. A request that sends, charges, posts or creates can succeed on the server and still time out before the response gets back, and the retry then does it a second time, and nothing errors, because both calls worked exactly as instructed. Retrying a write needs an idempotency key on the receiving end, which has to be built rather than configured. The long version, including why this bites hardest with agents, is in the section on rollback in the AI agent guide. The short rule: anything a customer would notice happening twice needs a key before it gets a retry.

Don't treat a spreadsheet as a key-value store with constraints. If the identity of a row matters, keep the key somewhere that can refuse a second write, such as a database column with a unique constraint. On self-hosted n8n you can narrow the overlap window with N8N_CONCURRENCY_PRODUCTION_LIMIT=1, but note that this is instance-wide rather than per-workflow. The full version is in Build 3 of the Google Sheets guide.

If you are importing workflows from a template library, our guide to vetting a template before you run it covers the rest of the review. On this evidence, "does it handle failure" belongs on that checklist, because four times out of five it does not.

Can you trust these numbers?

Partly, and the boundary is worth being precise about, because this dataset has known problems that other people found and documented before we got to it.

Three of the five top-level objects in these files have been rewritten at some point in the repo's history. Two of the three were reported publicly before we started:

  • The connections are broken. Issue #200, filed 4 September 2026, reports that 27,525 of 27,544 connection targets point at nodes that do not exist in their files, mostly synthetic error-handler-<uuid> names, across 1,363 files. We reproduced it independently and got the same figures.
  • The node types are wrong for AI nodes. The same issue reports that every scoped @n8n/n8n-nodes-langchain.* type was replaced with n8n-nodes-base.noOp. We confirmed it: exactly one node in the entire corpus still carries a scoped type, while 2,053 AI-named nodes are typed as no-ops.
  • The published stats were inflated. Issue #190 documents README badges claiming 4,343 workflows against 2,061 real files, a number hand-edited into stats.json rather than derived from the data.
  • settings and meta are normalised. All 2,026 files that carry settings carry a byte-identical one, and every meta.createdAt falls on 29 September 2025 within microseconds.

So why is anything here believable? Because the per-node error-handling properties survived all of it, and we checked that rather than assuming it. Taking one workflow rich in those fields and reading it at three points in the repo's history: before the type rewrite, at it, and at HEAD:

c4885eee (Aug 2025)3c0a92c4 (Sep 2025)HEAD
retryOnFail474747
onError: continueRegularOutput131313
maxTries666
waitBetweenTries171717
alwaysOutputData444

Identical throughout, while @n8n/ types went 11 to 0 and connections went from fully resolving to not resolving at all. The rewrites hit type, connections, settings and meta, and left node properties alone.

What that permits, and what it forbids. Every statistic on this page reads node properties or unscoped n8n-nodes-base.* types, both of which we have reason to trust. We also checked that no node named like an Error Trigger or a Google Sheets node had been mistyped, and none had. What we deliberately do not claim is anything about how workflows are wired: whether an error output actually connects to something, which nodes follow which. We had a number for that and threw it away, because the graph in this dataset is not real.

The last caveat is the honest one: these are files people publish and download, not a sample of what runs in production. Nobody has that dataset. What these numbers describe is what the ecosystem hands you when you import a template.

Reproduce this

Every number here comes from five short Python scripts run against a shallow clone. Nothing is hand-counted and nothing is estimated.

git clone --depth 1 https://github.com/Zie619/n8n-workflows.git corpus
python dedupe2.py   # 2,061 files -> 2,030 unique workflows
python analyze2.py  # the error-handling table
python sheets.py    # Google Sheets operations
python cross.py     # upsert workflows crossed with error handling
python fab.py       # the connection check, reproducing issue #200

The repo is a moving target. It had 56,594 stars and a last push of 24 June 2026 when we cloned it. If your numbers differ from ours, the clone date is the first thing to check.

Frequently asked questions

Does 84.8% mean most n8n workflows are broken?

No, and the distinction matters. It means most of these files declare no error handling. A workflow with no retry on an HTTP node is not broken; it fails on a bad day instead of recovering from one. What the number says is that failure is not something most published workflows have been designed around.

Why not just check each workflow's own error-workflow setting?

Because in this corpus that field is worthless. All 2,026 files carry errorWorkflow: null as part of an identical injected settings block, so the value tells you about whoever assembled the repo and nothing about whoever wrote the workflow. We detected Error Triggers by looking for the node instead.

Is continueOnFail the same as onError: continueRegularOutput?

Yes, in effect. continueOnFail: true is the older spelling and n8n replaced it with the onError field, which has the advantage of distinguishing "pass the error downstream" from "send it out a separate output". 43 workflows still use the old field. We counted both and treated them the same.

Can I trust the rest of this corpus for my own analysis?

For node properties, we think so, on the evidence above. For node types, only the unscoped n8n-nodes-base.* ones, and anything scoped is gone. For connections, settings, metadata or timestamps, no. If you read a statistic about this dataset anywhere, the useful question is which fields it was computed from.