I wrote a free linter for n8n workflows: 12 checks for the failures that cost money
Most n8n reviews look at the happy path. The expensive failures are elsewhere: the run that dies quietly, the message that gets marked read and never recorded, the retry that sends twice, the handover note that promises threading the send node cannot do.
I turned the checks I use when auditing workflows into a small script. It reads an exported workflow JSON and reports what it finds. No instance access, no credentials, no network, no dependencies.
What it checks
| Severity | Rule | What it catches |
|---|---|---|
| high | no-error-workflow |
No error workflow set - failures are silent |
| high | imap-read-before-log |
Mail marked read before it is recorded |
| high | confidence-defaults-high |
A missing confidence value treated as certain |
| high | threading-claim-false |
Docs promise In-Reply-To that the node cannot set |
| high | autosend-hardcoded-on |
Auto-send hardcoded, human gate gone |
| medium | http-no-retry |
A transient 502 kills the whole run |
| medium | webhook-open |
Webhook accepts unauthenticated requests |
| medium | no-idempotency |
A retried trigger is processed twice |
| medium | no-send-log |
Sends mail, records nothing |
| medium | empty-draft-sendable |
An empty draft can reach the send step |
| low | trigger-doc-mismatch |
Node name contradicts its schedule |
| low | http-no-timeout |
Hung HTTP call blocks the queue |
What it found in my own template
I ran it against my own published workflow (Triage inbound email with IMAP, custom AI HTTP APIs and SMTP | n8n workflow template). Four high findings, including the one I am least proud of: the sticky notes claimed In-Reply-To / References were set, and the send node had an empty options object. n8n’s Send Email node does not support those headers at all - every reply opens a new conversation. My documentation was describing something impossible, which is worse than simply not threading.
That is the point of the tool: it found the lie in my own handover note before a customer did.
Usage
python n8nwf_lint.py workflow.json
python n8nwf_lint.py workflow.json --json # for CI
python n8nwf_lint.py workflow.json --min-severity high
Exit code is 1 when findings meet the threshold, so it works as a CI gate unchanged.
Repo: GitHub - Miss567/n8nwf-lint: Static reliability checks for exported n8n workflows - silent failures, missing retries, false threading claims. No dependencies, MIT. · GitHub - MIT, Python 3.8+, no dependencies.
Two honest notes. It is a static heuristic check on the graph, not a behavioural test - it cannot see runtime data, so it will miss things and may flag things you consider fine. If a rule is wrong, tell me and I will fix it; that is more valuable to me than a star.
And yes, I do this for a living: a fuller audit is USD 45, and fixes are quoted before starting. The tool being free is not a trick - if the report is enough for you to fix it yourself, that is a good outcome.
Sample output: the screenshot below is the real report on my template.
If you want the client-facing part: the free script prints findings; the paid kit turns the same checks into a branded HTML/PDF audit report you can hand to a client (one command, your name and the client’s name on it): https://payhip.com/b/ZHoiv - USD 19.
