A red execution in n8n is easy. You see the error, you fix it. The expensive failures are the green ones: the workflow finishes with status "success", but it took the wrong branch, read an empty variable, or processed items in an unexpected order. Nobody notices until a customer asks why they never got the email.
In this tutorial you will learn to spot three silent errors that I ran into in real client projects, how to find them in the exported workflow JSON, and how to make the next one loud instead of silent. All three examples are small workflows you can rebuild in a few minutes.
Prerequisites: a running n8n instance (self-hosted or cloud) and basic familiarity with the editor. Version differences matter here, so check the notes in each section against your own version.
What is a silent failure?
A silent failure is a run that ends with status "success" while the result is wrong. n8n only marks an execution as failed when a node throws. A condition that evaluates to the wrong value does not throw. An expression that returns undefined does not throw. So the run is green, and your monitoring is green too.
The defence is the same in all three cases: make the assumption explicit, then make a violation visible.
Error 1: The If node with a missing combinator
Imagine you want to continue only when an order has a total above 100 and a valid email. In the If node you add two conditions. You expect both to be required.
Open the workflow, copy it to the clipboard and paste it into a text editor. Look at the node parameters:
{
"name": "Order valid?",
"type": "n8n-nodes-base.if",
"parameters": {
"conditions": {
"conditions": [
{ "leftValue": "={{ $json.total }}", "operator": { "type": "number", "operation": "gt" }, "rightValue": 100 },
{ "leftValue": "={{ $json.email }}", "operator": { "type": "string", "operation": "exists" } }
],
"combinator": "and"
}
}
}
The line that matters is "combinator". In the editor it is the small "AND / OR" switch between the conditions. If the switch is set to OR, or if a workflow was built from an older template, the node lets an item through when only one of the two conditions is true. The run is green and orders without an email go down the "valid" branch.
How to check it every time:
- Export the workflow and search the JSON for
"combinator". - For every If and Filter node, confirm that the value matches what you intended.
- Add a test item that violates exactly one condition, and confirm that it ends up on the "false" branch.
That third step is the important one. A test with one violation per condition costs two minutes and catches this class of bug for good.
Error 2: process.env versus $env in Code nodes
Secrets such as API keys belong in environment variables, not in the workflow. The natural instinct, if you write JavaScript, is this:
const apiKey = process.env.MY_API_KEY;
In a Code node this may give you undefined, because n8n restricts access to environment variables from inside nodes. The supported way is the $env helper:
const apiKey = $env.MY_API_KEY;
if (!apiKey) {
throw new Error('MY_API_KEY is not set');
}
return [{ json: { hasKey: true } }];
Two details make this a silent failure. First, if you build a header like Bearer ${apiKey} with an undefined value, you get the string Bearer undefined. The API answers 401, and if the HTTP node is set to continue on error, the run stays green. Second, whether $env is readable at all depends on your instance configuration. Depending on the n8n version, access can be blocked or limited to an allowlist through environment settings. Check the configuration reference for your version instead of assuming the default.
The fix is the guard in the example above: throw an error when the variable is missing. A missing secret now produces a red execution on the first run.
Error 3: The execution order setting
Workflows with branches that merge again can behave differently depending on the execution order setting in the workflow settings. In the exported JSON it appears like this:
"settings": {
"executionOrder": "v1"
}
Older workflows may still use the legacy order. With v1, n8n finishes one branch completely before it starts the next one, in a defined order based on node position. With the legacy order, nodes run in a different pattern, and a node that reads data from "the previous node" or from a named node can get data from a different branch than you expected.
The symptom is a Merge or Set node that quietly uses data from the wrong branch. Nothing throws.
How to check:
- Open the workflow settings and note the execution order.
- If the workflow has parallel branches, run it with an input that makes the branches produce clearly different values.
- Open the execution and compare the data in the Merge node with what you expect.
If you must migrate an old workflow, change the setting on a copy and compare the outputs for the same input before you replace the original.
Make the next failure loud: an error workflow
Even with these checks, you will miss something. The last line of defence is an error workflow that tells you about red executions, plus an explicit "sanity" node that turns suspicious green runs into red ones.
Create a new workflow with an Error Trigger node, followed by a node that sends you a message (email, chat, whatever you read daily). Then open the settings of your production workflow and select it as the error workflow.
For wrong-but-green runs, add a Code node at the end:
const items = $input.all();
if (items.length === 0) {
throw new Error('No items reached the end of the workflow');
}
const missing = items.filter(i => !i.json.email);
if (missing.length > 0) {
throw new Error(`${missing.length} item(s) without email reached the end`);
}
return items;
Now an empty result or an item without an email is a red execution, and the error workflow sends you a message.
Checklist
- Every If and Filter node: confirm the combinator in the JSON.
- Every Code node: use
$env, and throw when the value is missing. - Every HTTP node with "continue on error": make sure a later node checks the status code.
- Workflow settings: know your execution order and test branches with different values.
- One error workflow connected to every production workflow.
- One test item per condition that must fail.
Conclusion
Green does not mean correct. The three errors above share one pattern: n8n did exactly what the configuration said, and the configuration did not say what the author meant. Reading the exported JSON, adding guards that throw, and connecting an error workflow turns these quiet problems into visible ones.
I published three small example workflows for these cases under the MIT license: https://github.com/St-ton/n8n-stolperfallen
Top comments (1)
The "Bearer undefined" case is a classic. Continue On Error plus a 401 is a common green-but-wrong pattern, because the error output looks like a normal item to every node after it.
One more silent one worth adding: an HTTP Request that returns 200 with an empty list. The run stays green and nothing downstream ever executes, so you only notice days later. A small If node that fails the run when an item count you expect to be non-zero comes back as zero catches that early.