Guides / Monitoring guides

Why n8n workflows fail silently, and how to get alerted

Updated · 6 min read

The failure modes that never produce a failed execution, and how to add an Error workflow plus a heartbeat so you hear about all of them.

n8n is good at telling you when a node throws. Open Executions, filter by error, and the failed run is there with the node that broke. The failures that hurt are the ones that never become a failed execution. The workflow doesn't run at all, or it runs, ends in a green "Success", and does nothing useful.

This guide lists the common ways that happens and what n8n gives you out of the box. It then walks through a setup that covers both kinds of failure: an Error workflow for loud failures, and a heartbeat ping for silent ones.

The ways an n8n workflow fails without an error

1. The trigger never fires. If nothing starts an execution, there is nothing to fail. Common causes:

  • The workflow was deactivated (unpublished) while someone was editing it, or after an import, and never switched back on.
  • The n8n instance, or its queue-mode workers, stopped or restarted and didn't come back healthy. A self-hosted container that runs out of memory is a classic.
  • A Webhook trigger is being called on its test URL instead of the production URL, or the sender changed the URL.
  • A Schedule Trigger was edited and now fires at a different time, or a polling trigger's credentials expired.

An error workflow can't help here. It only runs when an execution fails, and in these cases no execution exists. If the whole instance is down, the error workflow is down with it.

2. A node returns zero items. When a node outputs no items, n8n doesn't run the nodes after it on that branch, and the execution can still finish as a success. A search that suddenly matches nothing, an API that returns an empty list, or a Filter node that drops everything all produce a "successful" run that wrote nothing. The node setting Always Output Data changes this, but it's off by default for good reason.

3. Errors are swallowed on purpose. Each node has an On Error setting: Stop Workflow, Continue, or Continue (using error output). Continue is handy during development and dangerous later. The node fails, the workflow keeps going with the last valid data, and the execution is not marked as failed.

4. The run "works" but the output is wrong. An API returns 200 OK with {"error": "quota exceeded"} in the body. An LLM node returns an apology instead of JSON. n8n has no way to know that's a failure unless you tell it.

What n8n gives you out of the box

  • Executions list. You can review past runs for one workflow or all of them. It's useful when you're looking, but it doesn't notify you.
  • Error workflows. Create a workflow that starts with the Error Trigger node. Then in each production workflow, open Options → Settings and pick it under Error workflow. One error workflow can serve many workflows. It receives the execution id and URL, the error message, the last node executed and the workflow name. For trigger failures it receives a trigger object instead.
  • Stop And Error node. Use it to force a failure when your own condition is met, for example "zero rows synced". That routes the case to the error workflow.
  • Retry On Fail. This node setting re-runs a failing node, which absorbs transient API errors.

Two details from the n8n docs are worth knowing. You can't test an error workflow by running the main workflow manually, because the Error Trigger only fires for automatic executions. And execution.id and execution.url are missing when the error is in the trigger node.

Step 1: create a monitor

In Flowhush, click New monitor and fill in three fields:

  • Name: the workflow's name, for example Nightly CRM sync (n8n).
  • Expected every (seconds): how often the workflow runs. Use 3600 for hourly or 86400 for daily.
  • Grace period (seconds): how late a run may be before you're alerted. Leave room for queueing and slow APIs. For example, use 600 for an hourly job and 3600 for a nightly one.

You get a ping URL like https://flowhush.com/p/YOUR-MONITOR-UUID. Treat it like a password: anyone who has it can ping the monitor.

Step 2: ping at the end of the workflow

Add an HTTP Request node as the very last node on the success path:

Method: GET
URL: https://flowhush.com/p/YOUR-MONITOR-UUID
Authentication: None
Send Query Parameters / Headers / Body: off
Options → Timeout: 10000

Then open the node's Settings tab:

Execute Once: on        (ping once per run, not once per item)
Retry On Fail: on       (Max Tries 3, Wait Between Tries 2000 ms)
On Error: Continue      (a monitoring hiccup shouldn't fail your workflow)

Execute Once matters. Without it, a last node that outputs 200 items sends 200 pings. Because the ping is the last node, it only runs when every earlier node produced data. That's exactly what makes the zero-items case visible: no data, no ping, and you get an alert.

To also check what the workflow produced (Pro plan output checks), send the data instead of a bare GET:

Method: POST
URL: https://flowhush.com/p/YOUR-MONITOR-UUID
Send Body: on
Body Content Type: JSON
Specify Body: Using JSON
JSON (expression): {{ JSON.stringify($json) }}

You can test the URL from a terminal before wiring it in:

curl -fsS -m 10 https://flowhush.com/p/YOUR-MONITOR-UUID
# OK

The monitor stays new until its first ping. After that, if no ping arrives within expected every + grace, it goes down and you get one alert. You get a recovery alert when pings resume.

Step 3: report errors immediately with /fail

A heartbeat alone tells you about a failed nightly run only after the grace period. To hear about real errors right away, add a branch to your error workflow that calls the monitor's /fail endpoint. If one error workflow serves several workflows, map the workflow name to its ping URL in a Code node (mode Run Once for All Items):

const e = $input.first().json;
const urls = {
  'Nightly CRM sync': 'https://flowhush.com/p/UUID-OF-CRM-MONITOR',
  'Lead enrichment': 'https://flowhush.com/p/UUID-OF-LEADS-MONITOR',
};
const url = urls[e.workflow?.name];
if (!url) return [];
const message = e.execution?.error?.message ?? e.trigger?.error?.message ?? 'unknown error';
return [{ json: { url, message, execution: e.execution?.url ?? null } }];

Follow it with an HTTP Request node:

Method: POST
URL (expression): {{ $json.url }}/fail
Send Body: on
Body Content Type: JSON
Specify Body: Using JSON
JSON (expression): {{ JSON.stringify({ message: $json.message, execution: $json.execution }) }}

A /fail ping marks the monitor down at once and sends the alert. The first 1 KB of the body is kept in the monitor's Recent pings, so the error message is one click away. The next successful ping sends the recovery notice.

What each layer catches

FailureError workflowHeartbeat ping
A node throws and the workflow stopsYes, immediatelyYes, after period + grace
Workflow deactivated or trigger not firingNoYes
n8n instance or workers downNoYes
A node outputs zero items, run ends "successfully"NoYes (the ping node never runs)
Node set to On Error: Continue hides a failureNoOnly if later nodes stop producing data
Run succeeds but output is empty or malformedNoWith output checks on the POST body (Pro and Team)

Use both. The error workflow gives fast, detailed alerts when n8n knows something broke. The heartbeat covers the cases where n8n doesn't.

Picking period and grace

The period is measured from the last successful ping, not from a calendar schedule. Set it to the normal gap between runs, then add grace for the worst normal delay. If a workflow only runs on weekdays, the weekend gap is about three days. Either set the period to cover it (259200 seconds) or pause the monitor over the weekend. Otherwise you'll get an alert every Saturday.

Try it on your own workflows

The Free plan includes 5 monitors with email, Slack, Discord or Telegram alerts. That's enough to cover your most important n8n workflows today.

Monitor your first workflows free

The Free plan includes 5 heartbeat monitors with alerts to email, Slack, Discord or Telegram. No credit card required.

Start free — 5 monitors   See setup snippets