debug-workflow
Skill32 starsChanged 7 months agoMITView on GitHub
Systematically debug failing n8n workflows — expression errors, node type mismatches, pinned data issues, sub-workflow failures, authentication problems, rate limit errors, and silent data loss. Use this skill whenever the user reports an n8n workflow problem — phrases like "my n8n workflow is failing", "this expression isn't working", "why is this node returning empty", "debug this error", "n8n execution log shows", "workflow runs but no output". Also use when pasted error messages reference n8n concepts (ItemLists, expressions, credentials). Apply this skill before guessing a fix — n8n failures have specific diagnostic patterns, and guessing typically makes the problem worse.
4 other projects use a version of this.
Adopted by
Most recently taken up by
- synaptiai/agent-capability-standardtheir own version, first seen Nov 1, 2026
- tammai/bigin-skillstheir own version, first seen Oct 11, 2026
- shioki/Cursor-Knowledge-Management-Systemtheir own version, first seen Oct 9, 2026
- bibektimilsina00/runmycrewtheir own version, first seen May 19, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- synaptiai/agent-capability-standard★ 6same name
- bibektimilsina00/runmycrew★ 1same name
- shioki/Cursor-Knowledge-Management-System★ 1same name
- tammai/bigin-skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository4 other files it gives its agents.
- chain-llm-patternSkill
- enrichment-waterfallSkill
- mysql-checkpointingSkill
- workflow-architectSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
13 rules. 0 are common, 7 are distinctive, and 6 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Ask the user (or infer from error text) which class:
- Very specific: line 33
Referencing earlier nodes: Use $('Node Name').item.json.field, NOT $node['Node Name'].json.field (deprecated).
- Very specific: line 65
Check: is it ONE item with an array inside ({ json: { list: [...] } }), or MULTIPLE items ([ { json: {} }, { json: {} } ])?
- Distinctive: line 78
Pinned data?: If a node has a pin icon, it's returning pinned test data, NOT real data.
- Very specific: line 88
Self-hosted n8n specific: if a credential suddenly stops working after a container restart, check that the encryption key …
- Very specific: line 96
Add Wait node between batches: waitBetweenBatches: ceil(60000 / requests_per_minute)
- Very specific: line 98
Check response headers (X-RateLimit-Remaining, Retry-After) and dynamically back off via a Code node
- Very specific: line 106
Parent didn't pass data: Check "Workflow Inputs" in the Execute Workflow node — must reference {{ $json }} or explicit fields.
- Distinctive: line 115
Look at ITS input (left). Is the shape what you expected?
- Distinctive: line 116
If input is wrong, the bug is UPSTREAM — trace back.
- Distinctive: line 117
If input is right but output is wrong/error, the bug is IN THIS NODE — check parameters.
- Distinctive: line 131
Ask the user for:
- Distinctive: line 137
Don't guess without these.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
n8n Workflow Debugging
Fix n8n workflows the way a senior engineer does — systematically, not by guessing.
Triage: identify the failure class first
Ask the user (or infer from error text) which class:
| Class | Symptom | Common root causes |
| Expression error | Cannot read property X of undefined, red node badge | Wrong expression syntax, missing = prefix, accessing undefined fields |
| Type mismatch | Expected string, got array, downstream weirdness | Item Lists vs single item confusion, Split In Batches output shape |
| Silent empty | Workflow runs green but no output/side effect | Filter condition wrong, pinned stale data, credential scope |
| Auth failure | 401, 403, Invalid API key | Wrong credential selected, expired token, OAuth refresh not configured |
| Rate limit | Intermittent 429, works manually, fails in batch | No backoff, batch too large, shared credential across workflows |
| Sub-workflow | Execute Workflow returns nothing or errors | Parameters not passed, return value not set, wrong workflow ID |
Expression errors
The single biggest footgun: ={{ $json.field }} vs {{ $json.field }}. The leading = makes the field an expression. Without it, the literal string {{ $json.field }} is sent.
Check:
- Click the field — does it show the "expression" toggle (fx icon) highlighted? If not, it's literal mode.
- In code-view JSON, the value should start with
=:"value": "={{ $json.id }}"
Accessing undefined paths: $json.customer.email throws if customer is null. Use optional chaining: $json.customer?.email ?? 'unknown'.
Referencing earlier nodes: Use $('Node Name').item.json.field, NOT $node['Node Name'].json.field (deprecated). Quote exact node name including spaces.
Common expression patterns:
// Array access
{{ $json.items[0].name }}
{{ $json.items?.[0]?.name ?? 'empty' }}
// Previous node output
{{ $('Webhook').item.json.body.email }}
// All items from previous node (for loops)
{{ $('Split In Batches').all().map(i => i.json.id) }}
// Conditional
{{ $json.amount > 100 ? 'high' : 'low' }}
// Date formatting (n8n uses Luxon)
{{ $now.toISO() }}
{{ $now.minus({ days: 7 }).toFormat('yyyy-MM-dd') }}
// Environment vars (self-hosted)
{{ $env.MY_SECRET }}Type mismatch diagnosis
n8n passes data as an array of items, each with { json: {...}, binary: {...} }. Many bugs come from treating a single item as an array or vice versa.
Inspection routine:
- Open the failing node's input view (left panel)
- Check: is it ONE item with an array inside (
{ json: { list: [...] } }), or MULTIPLE items ([ { json: {} }, { json: {} } ])? - These require different handling:
- Array-inside-one-item → use
Item Lists→ "Split Out Items" to fan out - Already multiple items → operate per-item
- Array-inside-one-item → use
Split In Batches outputs different shapes on main vs "done" outputs — the main output is a batch, the done output is empty. Wire accordingly.
Silent empty — the worst kind
Workflow shows green checkmarks but nothing happened downstream. Diagnostic order:
- Check execution data retention. Settings → "Save data successful executions" must be "All" during debugging, not "None".
- Inspect each node's output. Click each node → "Output" panel. Find the first one that's empty when you expected data.
- Pinned data? If a node has a pin icon, it's returning pinned test data, NOT real data. Right-click → Unpin Data.
- Filter / IF conditions. An
IFevaluating false silently skips the branch. Check the condition value at runtime. - Credential scope. Google/Microsoft OAuth credentials often have limited scopes. A "Google Sheets" credential won't let you read Gmail. Re-auth with correct scopes.
Authentication failures
- 401 on a previously-working workflow → token expired. Re-authenticate the credential.
- 401 immediately on a new workflow → wrong credential type. E.g., "Header Auth" vs "OAuth2" — check the API's docs.
- 403 with valid token → missing scope OR wrong account. OAuth credentials are per-account; confirm you authed with the right Google/Meta account.
Self-hosted n8n specific: if a credential suddenly stops working after a container restart, check that the encryption key (N8N_ENCRYPTION_KEY env var) is persisted. Losing it = all credentials corrupt.
Rate limit failures
Symptom: works on 10 items, fails on 100. Classic.
Fix pattern:
- Wrap the API call in
Split In BatcheswithbatchSizematching the vendor's per-second limit - Add
Waitnode between batches:waitBetweenBatches: ceil(60000 / requests_per_minute) - Set
retry.maxTries: 3withretry.waitBetweenTries: 5000on the HTTP Request node - Check response headers (
X-RateLimit-Remaining,Retry-After) and dynamically back off via aCodenode
For cron-triggered workflows hitting the same vendor from multiple cron jobs, centralize the API call in ONE sub-workflow with a semaphore pattern (MySQL row as lock).
Sub-workflow failures
Execute Workflow returns null or undefined most often because:
- Parent didn't pass data. Check "Workflow Inputs" in the Execute Workflow node — must reference
{{ $json }}or explicit fields. - Child didn't set output. The LAST node in the sub-workflow's output becomes the return value. If the last node is a
MySQLinsert returning nothing, parent gets nothing. Add a finalSetnode that constructs the return payload. - Wrong workflow ID. Sub-workflow got deleted and recreated → new ID → reference stale.
Reading n8n execution logs
Execution log shows per-node input and output. Debug pattern:
- Find the first failing node (red).
- Look at ITS input (left). Is the shape what you expected?
- If input is wrong, the bug is UPSTREAM — trace back.
- If input is right but output is wrong/error, the bug is IN THIS NODE — check parameters.
Most bugs are upstream shape issues masquerading as downstream errors. The error message lies about where the bug is.
Quick-fix checklist for common cases
- Expression not interpolating → add leading
= - Node says "No items to process" → upstream IF is filtering everything, or previous node returned empty
- Google Sheets append inserting duplicates → no unique constraint, add idempotency check (see
mysql-checkpointingskill) - LLM returns garbage JSON → switch from raw HTTP to
Information Extractorwith schema (seechain-llm-pattern) - Webhook times out → move heavy work behind
Respond to Webhook(respond first, process async)
When stuck
Ask the user for:
- Screenshot of the execution log (the red-bordered panel)
- The exact error message (copy-paste from the node)
- The node's parameters (settings tab, JSON view if possible)
- Whether this ever worked before (regression vs new bug)
Don't guess without these. n8n errors are specific — vague guesses waste time.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

