The Error Trigger only fires when an execution fails. But some failures never produce an execution at all: a webhook stops being called, a polling trigger loses its credentials, an upstream app changes something. Nothing runs, so nothing errors.
A few things I’m curious about:
What was the last time this happened to you, and how did you find out?
What do you do now to catch it? Heartbeat checks, a “did it run today” workflow, counting outputs, a monitoring tool, or just checking executions by hand?
For workflows that are legitimately quiet (run weekly, or only when a customer does something), how do you tell “nothing happened today” apart from “the trigger is dead”?
Would love to hear real examples, including setups that turned out to be overkill.
Describe the problem/error/question
What is the error message (if any)?
Please share your workflow
(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
Hi @uday_gurram, for scheduled workflows I’d use an external heartbeat, with an HTTP Request after the expected work succeeds. Healthchecks.io supports this: set the actual schedule plus a grace period, so a weekly workflow isn’t expected to report daily. Keep the alert outside that n8n instance, otherwise the monitoring workflow can stop alongside everything else.
For event-driven workflows, silence alone can’t distinguish “no customers today” from a dead trigger. A practical IMAP check would be an independently scheduled test email with a unique marker. The real IMAP trigger receives it, acknowledges it to the monitor, then routes it away from customer-facing actions. A direct webhook ping wouldn’t test that email delivery path.
Small correction on Error Trigger: it can also receive trigger/activation errors before an execution exists. It still won’t catch an upstream system silently stopping deliveries.
Another option is to use an external free tool like [doyouok]. The workflow can call its Ping URL after a successful execution, and if the expected check-in doesn’t arrive within the configured interval, it can send an alert.
The advantage here is that the monitoring is outside n8n, so it can still detect a missing heartbeat if the workflow or trigger itself stops running.
@achamm’s recipe is basically what we run too, and two things bit us with it.
Limit 1 returns manual runs as well. Hit “Execute workflow” in the editor to test something and the dead schedule looks fresh again, since manual executions are saved by default. We fetch the last 20 and drop anything with mode manual before taking the newest.
The other one is pruning. EXECUTIONS_DATA_MAX_AGE defaults to 336 hours, so for a monthly workflow an empty result can mean the last run got deleted, not that it never ran. Same for workflows set to not save successful executions, they only ever show failures. Our check lists those as not covered instead of alerting.
On your question 3, @Anshul_Namdev’s canary is the only honest answer I know for event-driven ones. For schedules we take the interval off the trigger node and allow twice that before calling it dead.
Since it’s in the account name, we build an outside monitor (Duskwatch). It can’t tell a quiet webhook from a dead one either.
Detection is well covered above, so I’ll add a cause that’s worth deleting rather than monitoring for, because it did this to me roughly once a week for months.
If a workflow uses a Google credential, check whether the OAuth consent screen is still in “Testing” in Google Cloud. In that state Google expires the refresh token about every 7 days. The workflow stays active, the trigger looks healthy, and it just quietly stops doing anything, which is indistinguishable from “stopped triggering” unless you open an execution. Publishing the consent screen (Google Auth Platform > Audience > Publish, status becomes “In production”) ended it permanently for me.
Two gotchas when you do that: the Publish button stays greyed out until the Branding page is complete (app name, support email, home page, privacy and terms URLs, authorised domain), and do not upload an app logo, because that forces full Google verification. The unverified warning at sign-in afterwards is expected.
Also worth knowing: if one credential is shared across several workflows, a single token death takes all of them out at once, which is somehow easier to miss than one workflow breaking on its own.
Telling it apart from a transient failure, from the execution log:
“Service unavailable - try again later” is a 503 on Google’s side. Nothing is broken locally and retryOnFail fixes it. Worth setting, since n8n nodes default to no retry, so one 5xx kills the run.
invalid_grant or a 401 is the refresh token dying. Retrying will not help; it’s the consent screen.
Small note if you plan to fire synthetic runs at a schedule-triggered workflow: on self-hosted the public API can’t start one. POST to /workflows/{id}/run, /workflows/{id}/execute and /executions all return 405.
Good thread. Most of the answers here cover “did it run” healthchecks, heartbeats, canary pings.worth adding the adjacent failure mode: it ran, it logged success, and it still did the wrong thing silently.
Hit this on a content-generation workflow: the image step had a fallback for when the primary source failed, and the fallback kicked in silently. No error, no missing execution, Error Trigger never fired, because nothing actually threw. The workflow just quietly shipped a wrong/generic output instead of the real one, for days, before anyone noticed.
Fix was to stop treating “did a value come back” as the success check, and instead explicitly flag whenever the fallback branch gets used even though it technically succeeds and route that to a Slack alert separately from the Error Trigger. Basically: “ran successfully” and “produced the correct output” turned out to be two different things worth monitoring, not one.
Might be worth a #4 in your original question: for workflows with a fallback/default path, how do you tell a legitimate rare fallback from a silently broken primary source?
On your third question (quiet vs dead), the thing that finally worked for us was to stop asking the workflow whether it ran, and start asking the source what should have happened.
A heartbeat tells you the trigger fired. It can’t tell you whether firing 0 times today was correct. For that you need an expectation that lives outside the workflow, so we split it in two:
Scheduled workflows: easy. Expected cadence plus a grace window (DuskWatch’s 2x interval is a good rule).
Event-driven workflows: a separate scheduled check asks the source for its own count (new rows since X, emails matching the filter, form submissions) and compares it to what the workflow actually processed. Source says 4 and the workflow handled 0 → dead trigger. Source says 0 and the workflow handled 0 → just a quiet day. Without that comparison, the two look exactly the same.
The other change: we track each monitored workflow as a record with a state (Healthy → Overdue → Acknowledged → Resolved) instead of firing a one-off alert. Alerts get muted or lost. A record sitting in “Overdue” until someone looks at it and marks it Acknowledged doesn’t. It also gives you a history, so you can see that the same Gmail trigger has gone quiet three times this quarter, which usually points straight to the cause (like the OAuth Testing-mode expiry Nived mentioned).
It costs one extra API call per source, but it’s the only approach I’ve found that actually answers “is it quiet or is it broken.”
For the “quiet vs dead” question, the thing that worked for me is giving each workflow its own expected gap instead of one global rule:
Learn the cadence from history. Pull GET /api/v1/executions?workflowId=<id>&limit=50, take the median gap between startedAt values, and alert when now − last startedAt is more than ~2–3× that gap. A weekly workflow automatically gets a weekly window.
For event-driven workflows, ask the source. On a schedule, query the upstream app (“any new leads/emails since X?”). Source says yes but n8n has zero executions → the trigger is dead. Source says no → it’s just quiet.
Catch deactivations. Compare GET /api/v1/workflows?active=true with yesterday’s list. A workflow someone switched off never errors.
Watch the instance from outside. An external heartbeat ping (Uptime Kuma, Healthchecks) covers the case where n8n and your watchdog workflow are both down.
Disclosure: I work on FlowWatch, which runs this kind of missed-run check (plus error streaks and zero-item “successes”) from outside the instance via the public API: https://flowwatchhq.com