Your n8n workflow stopped three days ago. Nobody noticed, because nothing failed.
That is the failure mode nobody warns you about when you start automating: n8n is excellent at telling you when a node throws, and completely silent when a node returns zero items. The run goes green. The execution history shows a success. Your client finds out before you do.
Why an empty result looks like a good day
n8n reports failures at node level. An HTTP Request node that gets a 500 turns red and fires your error workflow. The same node getting a 200 with {"data": []} does what it was asked: it returns zero items, the nodes below it skip, and the workflow completes successfully.
For a lead-sync job, zero leads looks exactly like a quiet Sunday. For an invoice reminder, no invoices looks like a good month. Nothing in the UI tells you the difference, because from n8n's point of view there isn't one.
The four silent failures worth building against
1. The empty result treated as success. The API worked and had nothing for you. Fix: an IF node that checks item count, wired to a Code node that throws on zero.
// Code node, "Throw on empty" const items = $input.all(); if (items.length === 0) { throw new Error('Source returned 0 items'); } return items; A thrown error is the only kind n8n will tell you about, so you have to manufacture one.
2. The credential that quietly expired. OAuth tokens age out. Some APIs return 401 and the workflow fails loudly; others return an empty payload with a 200. Fix: a monthly test call to a known endpoint, with a failure path.
3. The schedule that never fired. Timezone shifts, an instance restart, a workflow deactivated by accident. No executions is not an error, so nothing alerts. Fix: a heartbeat workflow that reads the last execution time of your critical workflows.
4. The rate limit that returned success. Some APIs answer 200 with a partial body. You process what you got and report a win. Fix: compare received count against expected count and throw when the gap is large.
The 20-minute setup
Step 1. Create an error workflow: Error Trigger node into Slack, email or Telegram. Set it as the Error Workflow in every critical workflow's settings.
Step 2. Add validation after your data node. If the count is zero, throw. This is the single change that catches most incidents.
Step 3. Add a heartbeat. Every 30 minutes, ask the n8n API for the last execution of each critical workflow and throw if the newest successful run is older than expected.
Step 4. Write one row per run to a sheet or table. If yesterday's count is zero, you find out from data instead of from a client email.
Step 5. Alert on the first failure, not the third. One failure is a signal; three is an outage.
What to monitor first
Not everything needs a heartbeat. Start with workflows where a silent day costs money or trust: anything that sends client-facing email, creates invoices or orders, feeds a report someone decides from, or pulls data you would only notice missing at month-end.
Everything else can wait for the error trigger.
The part that is easy to get wrong
People build the alert and then ignore it, because it fires on noise. Two fixes: route low-priority alerts to a channel nobody reads and keep the main channel for revenue-affecting failures, and include the workflow name, the item count and the last successful run in the alert text. "Something broke" is not an alert, it is a puzzle.
The other mistake is monitoring the workflow instead of the outcome. A green run that produced nothing is the failure you are trying to catch, so the check belongs on the output, not on the execution status.
How to test that it works
An alert you have never seen fire is a rumour. Test it the week you build it.
Disable the credential on a test workflow and run it manually. Point the source at a filter that returns nothing. Deactivate one workflow and wait for the heartbeat window to pass. Each of those should produce exactly one alert in the right channel, with the workflow name and the reason in the text.
If nothing arrives, the problem is almost always one of three things: the error workflow is not set in that workflow's settings, the throw happens inside a node that is never reached because the branch above it skipped, or the alerting node itself needs a credential that expired. All three are invisible in the editor and obvious in a test.
What catching it late actually costs
Say a lead-sync workflow stops on Friday and the first sign is a client asking on Tuesday why no leads came in. You lost four days of pipeline, you cannot recover them, and the only thing you can tell the client is that you found out when they did.
The engineering cost of the setup is twenty minutes. The cost of the incident is a client relationship, which is not a twenty-minute problem. That ratio is why this is worth doing on a Saturday morning before anything else in the automation stack.
One more thing: the alert has to say what to do
The most common reason monitoring gets switched off is that the alerts are unactionable. "Workflow failed" at 2am tells the reader nothing except that they are about to lose sleep.
Include three things in every alert: which workflow, what the expected value was versus what arrived, and the first thing a human should check. With those, half of all alerts resolve without anyone opening n8n.
The full step-by-step, with the exact nodes and a table of what to monitor first, is on the site: Your n8n workflow stopped 3 days ago. Nobody noticed.
If you would rather import a pack than build it, there is a paid workflow for this pattern ($13, code VOXA20): Silent Failure Watch. The free method above is the same mechanism - the pack saves the setup time.
Originally published at voxahq.in.

