AI-skillGratis

n8n foutafhandeling

Gebaseerd op czlonkowski/n8n-skills @ 72470a0, licentie MIT

Bijgewerkt 30 augustus 2026

Dit bestand is door ToolBrain vertaald en inhoudelijk gewijzigd op 2026-08-30, op basis van n8n-error-handling SKILL.md uit czlonkowski/n8n-skills (MIT), zie de bron_url hierboven en ../LICENSES/n8n-skills-MIT.txt.

Standaard geldt in n8n: als één node een fout gooit, stopt de hele workflow. Voor een interactieve run die je zelf zit te volgen is dat prima — je ziet de rode node en fixt hem. Maar voor alles wat onbewaakt draait (een webhook-API, een cronjob, een queue-worker, een agent-tool) is dat de verkeerde default: de aanroeper krijgt een timeout of een lege 500, de beheerder krijgt geen alert, en het symptoom is "de integratie doet het gewoon niet meer" zonder log en zonder aanwijzing.

Deze skill gaat over het luid, gestructureerd en herstelbaar maken van fouten — en idealiter zelfherstellend, zodat tijdelijke haperingen nooit een mens bereiken.

Twee ideeën voorkomen de meeste stille storingen:

  • Per-node foutuitgangen — een falende node routeert naar een tweede, door jou gecontroleerde uitgang, in plaats van de run te doden.
  • Een workflow-brede foutworkflow — een vangnet dat afvuurt voor alles wat aan de per-node afhandeling ontsnapt (timeouts, crashes tussen nodes, niet-bedrade fouten).

Wanneer heb je dit echt nodig

WorkflowtypeVereiste foutafhandeling
Webhook/API (met "Respond to Webhook")Verplicht. Elke falende node z'n foutuitgang bedraad; statuscode past bij de oorzaak.
Gepland/cron/queue-worker/agent-tool (onbewaakt)Verplicht. Een workflow-brede foutworkflow, plus retry op netwerknodes.
Eenmalige interne run die je zelf bekijktOptioneel. De standaard "stop de workflow" is prima — je ziet de rode node en draait opnieuw.

De scheidslijn: zodra iemand anders dan jijzelf de output ziet — een downstream systeem, een eindgebruiker, een engineer met dienst — moet de fout afgehandeld worden, niet ingeslikt. Ben jij de enige kijker en is "ik merk het en draai opnieuw" acceptabel, dan mag het losser.

De grootste stille valkuil: een foutuitgang zetten is een TWEESTAPS-actie

Dit is dé manier waarop een n8n-workflow fouten lijkt af te handelen terwijl hij ze in werkelijk- heid inslikt. Een falende node naar een handler routeren vraagt twee wijzigingen, en slechts één ervan doen oogt compleet maar gedraagt zich verkeerd:

  1. Zet onError: "continueErrorOutput" op de node. Dit creëert de tweede uitgang. Zonder dit bestaat main[1] niet, hoe je ook bedraadt.
  2. Bedraad die foutuitgang (connections.<node>.main[1], dus sourceIndex: 1) naar een echte handler. Zonder doel verdwijnt de foutdata in het niets.
Wat je deedWat er in productie gebeurt
onError gezet, foutuitgang niet bedraadFoutdata wordt stilzwijgend weggegooid. Downstream vuurt niet. Het dashboard toont de run als geslaagd. Ergste geval: nergens een log.
Foutuitgang bedraad, onError niet gezetHet slot vuurt nooit; de handler is onbereikbaar. Bij een fout stopt de workflow gewoon (default stopWorkflow).
Beide gedaanFout routeert via main[1] naar je handler. ✅

Geldige onError-waarden: "stopWorkflow" (default, fout stopt de hele workflow), "continueRegularOutput" (foutitem stroomt via de normale uitgang — zelden juist, want downstream krijgt dan foutvormige data en gaat gewoon door), "continueErrorOutput" (foutitem stroomt via de aparte foutuitgang, die jij bedraadt).

Verifieer daarna altijd. Deze valkuil komt niet naar voren in een gewone validatie — een half bedrade foutuitgang valideert schoon. Haal de workflow op en controleer beide helften: staat onError echt op "continueErrorOutput", en bevat de bedrading van main[1] echt je handler.

Zelfherstel eerst: retry vóór je foutpaden bedraadt

Bouw eerst zelfherstel, zodat tijdelijke storingen die foutpaden nooit bereiken. Zet op elke node die een netwerkdienst aanroept — HTTP Request, communicatie (Gmail/Slack/Discord), databases, AI-nodes, integraties van derden — retry op node-niveau:

javascript
{ type: "updateNode", nodeName: "HTTP Request",
  changes: {
    retryOnFail: true,
    maxTries: 3,
    waitBetweenTries: 5000   // ms
  } }

Waarom dit eerst komt: een 429 of een kortstondige upstream-hapering lost zichzelf meestal op met een retry. De foutuitgang vuurt dan alleen bij echte, aanhoudende storingen — waardoor je 5xx-responses en on-call-alerts de werkelijke problemen weerspiegelen in plaats van ruis.

Engine-limieten om te kennen: retry vuurt op elke fout (geen filter per statuscode), maxTries plafonneert op 5, en waitBetweenTries plafonneert op 5000 ms — dus 5000 is zowel het maximum als een verstandige default.

API-workflows: de standaardvorm

Een webhook-getriggerde workflow die antwoordt aan de aanroeper kent één regel die alles overstijgt: geen hangende takken. Elk pad — succes én elke fout — moet eindigen bij een "Respond to Webhook"-node, anders blijft de aanroeper wachten tot de timeout.

Code
Webhook (responseMode: "responseNode")
  ├── input valideren → verwerken → Respond (200, body)
  └── (foutuitgang van elke falende node → sourceIndex 1)
            → Respond (4xx/5xx, gestructureerde foutbody)
            → optioneel: volledige fout privé loggen / notificeren

Drie dingen maken dit werkend:

  1. Fan-in naar één foutresponder. Veel falende nodes kunnen hun main[1] naar één Respond-node laten samenkomen — houdt de graaf overzichtelijk.
  2. Validatiefouten (4xx) worden vooraf gecheckt, niet via foutuitgangen. Een ontbrekend veld is geen crash — het is een verwachte uitkomst met een bekend antwoord. Vertak hierop met IF/Switch (of een schema-validator) en geef direct 400/401/403/404 terug. Foutuitgangen zijn voor onverwachte storingen (5xx).
  3. responseCode staat standaard op 200 — zelfs op foutpaden. Dit is zelf een stille valkuil: een foutpad dat 200 met een foutbody teruggeeft, ziet er voor de HTTP-client van de aanroeper uit als succes — hun eigen foutafhandeling vuurt dan nooit. Zet responseCode expliciet op elke Respond-node.

Input-validatie: valideer een gestructureerde payload met één enkele Set-node die een zelfaangeroepen functie draait, in plaats van een keten van IF/Switch-nodes per veld. Zo'n node geeft { valid, validationError, details, requiredSchema } terug, en een IF vertakt op valid naar je logica (200) of een 400-Respond die het schema teruggeeft zodat de aanroeper zichzelf kan corrigeren.

Responsvormen: koppel oorzaak aan statuscode

Een 5xx met platte tekst "Internal Server Error" is technisch een foutrespons maar praktisch onbruikbaar. En niet elke storing is een 5xx. Koppel de statuscode aan de wérkelijke oorzaak, want de aanroeper vertakt erop: hun monitoring alarmeert op 5xx (jouw schuld) maar niet op 4xx (hun schuld), en 5xx suggereert "opnieuw proberen" terwijl 4xx suggereert "niet doen".

OorzaakStatusFoutcodeWaar afgehandeld
Verplicht veld ontbreekt/verkeerd type400validation_errorVooraf (schema-validator/IF)
Authenticatie ontbreekt/ongeldig401unauthorizedVooraf
Geauthenticeerd maar niet toegestaan403forbiddenVooraf
ID geldig in request, ontbreekt in eigen data404not_foundVertakken op het opzoekresultaat
Conflicteert met huidige staat (dubbel, race)409conflictDetecteren met logica
Rate limit overschreden429rate_limit_exceededRetry-After-header zetten
Node gooide fout, oorzaak onbekend500internal_errorFoutuitgang
Externe API gaf een fout terug502upstream_errorFoutuitgang van de HTTP-node
Kan nu niet verwerken (downstream down)503service_unavailableSpecifieke fout detecteren, retry hinten
Externe API timede uit504upstream_timeoutFoutuitgang gefilterd op bericht

Kortom: 4xx wordt vóór het werk beslist (IF/Switch + eigen Respond), 5xx komt uit foutuitgangen ("we hebben het geprobeerd, het brak").

Eén Respond, expressiegedreven code. Verschillen foutpaden alleen in nummer en boodschap (dezelfde bodyvorm, dezelfde headers), splits dan niet naar N Respond-nodes via een Switch. De Respond-node accepteert expressies in zowel de responscode als de body — bereken de code inline met een korte IIFE die op basis van de foutboodschap 400/429/504/502/500 teruggeeft. Bewaar Switch + meerdere Responds voor paden die structureel verschillen (andere headers, andere bodyvorm, redirects).

De standaard envelope is { "error": "<code>", "message": "<leesbare tekst>" } — de HTTP-status zegt al succes-of-fout, dus geen aparte ok: false-vlag nodig. Lek nooit interne details (stacktraces, SQL, upstream-bodies, tokens) in de respons — log die privé, geef een geschoonde boodschap terug.

Workflow-brede foutworkflow (het vangnet)

Per-node-uitgangen vangen de fouten die je hebt voorzien op de nodes die je bedraad hebt. Een foutworkflow vangt al het andere: een node die je vergat te bedraden, een crash tussen nodes, een workflowbrede timeout, een trigger die faalt. Voor onbewaakte workflows is dit het vangnet dat "het stopte stilletjes" verandert in "er kwam een alert binnen".

Bouw dit als een aparte workflow die start met een Error Trigger-node. n8n roept die aan met de faalcontext (executie-ID, link naar de editor, laatst uitgevoerde node, foutnaam/-boodschap/ timestamp, workflownaam). Minimale versie — vastleggen → notificeren:

Code
Error Trigger → Set (alert opbouwen uit executie + fout) → Slack/mail (naar #incidenten)

Een goede alert bevat de workflownaam, een link naar de editor én naar de gefaalde executie, de naam van de gefaalde node, en de echte foutboodschap (niet "Workflow failed").

Twee valkuilen om vooraf te benoemen:

  • De recursieval. Notificeert de foutworkflow via Slack en is Slack juist wat down is, dan faalt de foutworkflow ook — en de oorspronkelijke fout verdwijnt. Notificeer op een ander kanaal dan je gemonitorde workflows gebruiken (bijvoorbeeld: workflows alarmeren via Slack, de foutworkflow gebruikt e-mail), en voeg een terugvaloptie toe (wegschrijven in een aparte tabel) zodat een mislukte notificatie toch een spoor achterlaat.
  • Een "afgehandelde" fout borrelt niet omhoog. Is de foutuitgang van een node bedraad naar een no-op die de data laat vallen, dan beschouwt n8n de fout als afgehandeld en vuurt de foutworkflow niet. Vang per node alleen af als je ook echt iets met de fout doet.

Wat via de tooling niet lukt: het toewijzen van de foutworkflow (instantiestandaard of per workflow) is een instelling in de n8n-UI zelf (Workflow Settings → Error Workflow) — daar bestaat geen programmatische route voor. Bouw de foutworkflow, en vertel de gebruiker precies welke UI-stap nodig is, en dat die herhaald moet worden (of als instantiestandaard gezet) voor elke onbewaakte workflow.

Wat niet beschikbaar is via de programmatische route

Naast het toewijzen van de foutworkflow zijn ook andere workflow-instellingen (Save Execution Data, tijdzone, timeout, aanroepbeleid) alleen via de UI in te stellen, en instantiebrede foutlogging (Sentry, serverlogs) is instantieconfiguratie buiten de workflows om. Wat wél programmatisch kan: de foutworkflow bouwen, onError/retryOnFail op nodes zetten, foutuitgangen bedraden (sourceIndex: 1), valideren, veelvoorkomende problemen automatisch oplossen, testen, en gefaalde executies inspecteren.

Antipatronen

AntipatroonWat er misgaatFix
onError gezet maar foutuitgang niet bedraadFout stilzwijgend weggegooid; run toont als geslaagdBedraad sourceIndex: 1 naar een echte handler, of zet onError terug op stopWorkflow zodat het luid is
Foutuitgang bedraad maar onError niet gezetSlot vuurt nooit; handler onbereikbaar; workflow stopt bij foutZet onError: "continueErrorOutput"
Webhook → verwerken → respond, geen foutpadAanroeper krijgt timeout of generieke 500Bedraad elke falende node se foutuitgang naar een Respond
Foutpad geeft 200 met een {error}-body terugClient van de aanroeper leest succes; hun foutafhandeling vuurt nooitZet responseCode expliciet op 4xx/5xx bij foutresponses
Eén 500 internal_error voor allesAanroeper kan eigen fout niet onderscheiden van jouw storingKoppel oorzaak aan status (4xx aanroeper, 5xx jij)
Fouten opvangen in een Code-node en als data teruggevenDownstream verwerkt foutvormige data en gaat doorLaat het gooien; gebruik onError: "continueErrorOutput" + bedraad pad
Netwerknode zonder retryOnFailElke tijdelijke 429/hapering wordt een 5xx; alerts vuren op ruisretryOnFail: true, maxTries: 3, waitBetweenTries: 5000
Switch → N Responds die alleen in statuscode verschillen5 nodes voor wat één Respond kanBereken de code inline in één expressiegedreven Respond
Onbewaakte workflow zonder foutworkflowEen echte storing gaat nergens heenBouw een Error Trigger-workflow + wijs 'm toe in de UI
Foutworkflow notificeert hetzelfde kanaal als de gemonitorde workflowsKanaal down → foutworkflow faalt ook → fout verdwijntAnder kanaal + terugvaloptie
Foutdetails (stack/SQL/tokens) lekken in de responsInterne details blootgesteld aan aanroepers/aanvallersPrivé loggen, geschoonde boodschap teruggeven

Checklist

Voor een API/webhook-workflow: webhook-trigger gebruikt responseNode-modus, input vooraf gevalideerd met een 4xx-Respond, elke falende node heeft continueErrorOutput én bedraad main[1], netwerknodes hebben retry geconfigureerd, elk foutpad eindigt bij een Respond met expliciete 4xx/5xx-code, statuscode past bij de oorzaak, foutbody bevat geen stacktraces/SQL/ tokens, en beide helften zijn geverifieerd door de workflow op te halen.

Voor een onbewaakte (gepland/cron/queue) workflow: netwerknodes hebben retry, er bestaat een Error Trigger-workflow (vastleggen → notificeren, optioneel retry), de foutworkflow notificeert op een ander kanaal met een terugvaloptie, en de foutworkflow-instelling is toegewezen in de n8n-UI.

Samenvatting

Onthoud: de default is stilte. Foutafhandeling is twee stappen — maak dat de fout routeert (per-node onError + bedrade uitgang, of een vangnet-foutworkflow) en maak dat hij spreekt (een statuscode en body die de waarheid vertellen). Een halve stap is erger dan geen stap, want het oogt afgerond.

Praktijkvoorbeeld (NL)

Een Nederlandse boekhoudservice voor zzp'ers laat een n8n-workflow elke nacht facturen ophalen uit een externe factuur-API en ze doorzetten naar het eigen klantportaal. Aanvankelijk stopte de hele nachtelijke run stil bij elke tijdelijke 502 van de factuur-API, zonder dat iemand het merkte tot een klant een week later belde over een ontbrekende factuur. Na het toepassen van deze skill kreeg de HTTP Request-node retryOnFail met drie pogingen, kreeg de node ook een bedrade foutuitgang naar een Error Trigger-workflow die via e-mail (bewust een ander kanaal dan de Slack die voor gewone meldingen wordt gebruikt) het administratieteam waarschuwt met de naam van de gefaalde klant en de echte foutmelding, in plaats van een generieke "workflow mislukt".