Feature
The failure n8n calls 'success' — and how we catch it.
A workflow runs every night. n8n marks every execution success. After four weeks of green checkmarks the client realises their CRM hasn't been updated since the credential scope changed. There's no error in the logs because nothing threw — the upstream API just started returning an empty array. WorkflowRadar's silent-failure detection is built for this exact case.
Why n8n calls broken workflows successful
n8n's execution status is bound to did any node throw an exception? — not did the workflow do its job. A Stripe API call that returns [] isn't an exception. A filter that drops every row isn't an exception. A credentials scope downgrade that silently lets an HTTP request through with reduced permissions isn't an exception. None of these surface in the execution log as failures. They're flagged success, the next downstream node runs against the empty result, and the workflow finishes "successfully" — producing nothing.
The native error workflow pattern doesn't help here. An error workflow only fires when n8n catches an exception. The thing that actually went wrong never threw, so the error workflow never runs.
What we detect
Every sync we look at the most recent successful executions of each workflow and extract a schema-only shape for each node:
- Input item count (items received from upstream)
- Output item count (items emitted to downstream)
- Distinct top-level field names in the output (just the names — never the values)
- Whether the run had an error block
- Whether the output was empty
Two heuristics run against this shape, gated by a historical baseline computed from the workspace's own prior runs:
- Empty terminal node: the workflow's last node emitted zero items. We only flag this when the node's historical median output was non-zero — a "no work today" workflow doesn't false-flag on a quiet day.
- Item count collapse: a non-utility node received 10+ items and emitted zero, against a historical median that was non-zero. Filter, IF, and Switch nodes are excluded — their job is to drop items, so zero output is by design.
When a workflow trips either heuristic, the workspace's diagnosis panel shows a "Silent failure detected" badge with the specific signals (e.g. empty_terminal:Send Slack Message, collapse:Filter active → 0). The AI root-cause diagnosis sees the same signals and leads with them.
Privacy posture
The shape extractor walks n8n's execution payload and copies only counts, field names, and boolean flags. Values are never touched. Field-name caps stop a pathological payload from leaking JSON-as-key into the diagnosis prompt:
- Field name length capped at 64 characters
- ≤50 distinct field names retained per node
- ≤20 runs retained per node
- ≤100 nodes retained per execution shape
When the AI diagnosis ships those shapes to the model, it sees Node "Fetch Stripe Customers": run 1: in=1 → out=247 (fields: id, email, created) — never the customer email itself, never the customer id, never the prompt content. The single source of truth for raw error text remains the execution's own error_message column, which sees the same secret-scrubbing path every other LLM input goes through.
How it shows up
Three surfaces consume the signals:
- Workflow diagnosis panel: a "Silent failure detected" badge above the diagnosis text, with a tooltip listing the specific signal names.
- AI root-cause text: the LLM prompt includes the per-node shape and is instructed to lead with the empty-output node as the most likely root cause when its historical median was non-zero.
- Alerts: when alerts are enabled and a silent failure is detected, the workflow fires an alert (sharing the same dedup bucket as health-status failures so you don't get two alerts at once for the same incident). Routes to email and to your Slack webhook if configured. Opt-out toggle in workspace alert settings.
Available on
Silent-failure detection is on every paid tier — see pricing. The AI diagnosis text that explains whythe empty output happened is part of the AI add-on; the detection itself isn't.
