How to Debug Failed n8n Workflows and Catch Errors in Production (2026)
Find the node that broke, read its input, and set up an Error Workflow that records every failure in n8n so nothing fails silently.
On this page
An n8n workflow that fails while you are watching is easy: the node turns red and the error is right there. The expensive failures are the other kind: a production execution that broke at 3 a.m., a webhook that stopped receiving data, an AI Agent node that started returning nonsense after an API change. Nobody sees them until a customer does.
This guide covers both halves: how to debug a failed n8n workflow step by step, and how to set things up so no failure goes unnoticed again.
Step 1: Find the failed execution
Open the workflow and go to the Executions tab, then filter by status Error. Each failed run shows when it ran, how long it took and which node stopped it. Open the most recent one: n8n loads the execution with the data of every node as it was at that moment.
If the list is empty although you know the workflow failed, check the workflow settings. Failed production executions are only kept when Save failed production executions is enabled (it is on by default, but self-hosted instances sometimes turn it off to save space).
Step 2: Find the node that broke and read its input
The failing node is marked in red, with the error message on it. Before reading the error, read the node's input: in most failed workflows the node itself is fine and the data it received is not. Look for:
- A field that is missing,
nullor empty. - A different shape than usual: a list where you expected one item, a string where you expected a number.
- An upstream API response that changed format.
If the input looks wrong, walk backwards node by node until you find where the data stopped matching what the next node expects. That node is the real cause.
Step 3: Reproduce without re-triggering
You do not need to resend the webhook or wait for the next schedule to test a fix:
- Pin data. In the output panel of a node, pin its data. The next manual runs reuse it, so you can rerun everything downstream with the exact input that failed.
- Debug in editor. On plans that include it, a past execution can be loaded straight into the editor with its data, so you can fix and rerun from the failure point.
Step 4: Match the error to its usual cause
| Error you see | Usual cause | Fix |
|---|---|---|
401 or 403 from an API node | Expired or revoked credentials | Reconnect the credential; prefer OAuth where it refreshes itself |
Cannot read properties of undefined | An expression points to a field that is not there for this item | Guard the expression or add an IF node before it |
| Webhook works in tests, not in production | The test URL is configured instead of the production URL, or the workflow is inactive | Use the production URL and activate the workflow |
429 Too Many Requests | Rate limit of the external API | Turn on Retry On Fail with a wait, or batch the requests |
| Timeouts | A slow API or a huge payload | Raise the node timeout, paginate, or split the work |
| AI Agent node returns the wrong format | The model's output changed or a tool failed silently | Validate the output with a structured parser and treat tool errors as errors |
Step 5: Make every failure visible with an Error Workflow
Debugging is reactive. The goal is to learn about failures before anyone else does. n8n has a built-in mechanism for this:
- Create a new workflow that starts with an Error Trigger node.
- Add what should happen on failure: a Slack or email node to notify the team, and a node that records the failure somewhere you can analyse it later.
- In the settings of each production workflow, set Error workflow to the one you just created.
From then on, every failed execution of those workflows runs the error workflow. The Error Trigger receives the details: the workflow name and id, the execution id and its URL, the node that failed (lastNodeExecuted) and the error message.
Step 6: Record every failure in Voight
Notifications tell you that something failed. To see patterns (which workflow fails most, since when, whether a fix held), the failures need to land in one place. Voight accepts events over a plain HTTP API, so the error workflow can send each failure with an HTTP Request node:
- Method:
POST - URL:
https://api.voight.xyz/v1/events - Header:
Authorizationwith the valueBearer vk_YOUR_KEY(store it as an n8n credential, not in the node) - Body: JSON, written as an expression:
{{ {
agentId: 'n8n-production',
type: 'error',
outcome: 'failed',
toolExecuted: $json.execution.lastNodeExecuted,
errorMessage: $json.execution.error.message,
metadata: {
source: 'n8n',
workflowId: $json.workflow.id,
workflowName: $json.workflow.name,
executionId: $json.execution.id,
executionUrl: $json.execution.url
}
} }}
A few notes:
agentIdis the label the failures appear under in Voight. Use one per n8n instance or per team.metadata.source: 'n8n'withworkflowIdandworkflowNametells Voight these are n8n failures, so each issue shows the workflow it came from and the node that broke.- Building the body as an expression keeps quotes inside error messages from breaking the JSON.
- The HTTP path does not scrub data for you. Error messages can contain tokens, emails or customer data from the failed request, so leave out the stack trace and anything you would not put in a log.
- A successful call returns
202 Accepted.
With failures arriving, Voight groups them by pattern into issues, so twenty executions failing on the same node with the same error show up as one problem with a count, not twenty notifications. Each issue tracks whether it came back after you marked it fixed, and Diagnose with AI proposes a root cause and a fix from the recorded failures. Keep the Slack or email node in the error workflow for paging: Voight shows alerts in its dashboard, and does not send them to Slack or email yet.
Hardening checklist
- Every production workflow has an error workflow set.
- Nodes that call external APIs use Retry On Fail with a wait between tries.
- Nodes set to continue on error are deliberate: they hide failures if the next node does not check the result.
- Expressions that read optional fields are guarded.
- Credentials that expire are monitored, or replaced by ones that refresh.
- Failed production executions are saved, so there is always something to debug.