Fehlerbehebung in n8n-Workflows
Repariere n8n-Workflows so, wie es ein Senior Engineer tut – systematisch, nicht durch Raten.
Triage: Identifiziere zuerst die Fehlerklasse
Frage den Benutzer (oder leite aus dem Fehlertext ab), welche Klasse vorliegt:
| Klasse | Symptom | Häufige Ursachen |
|---|---|---|
| Ausdrucksfehler | Cannot read property X of undefined, rotes Node-Badge | Falsche Ausdruckssyntax, fehlendes =-Präfix, Zugriff auf undefinierte Felder |
| Typkonflikt | Expected string, got array, seltsames Downstream-Verhalten | Verwechslung von Item Lists mit Einzelobjekten, Ausgabeform von Split In Batches |
| Stille Leere | Workflow läuft grün, aber keine Ausgabe/Nebenwirkung | Filterbedingung falsch, veraltete Pinned-Daten, Credential-Bereich |
| Authentifizierungsfehler | 401, 403, Invalid API key | Falsches Credential ausgewählt, abgelaufener Token, OAuth-Refresh nicht konfiguriert |
| Rate Limit | Gelegentlich 429, funktioniert manuell, schlägt im Batch fehl | Kein Backoff, Batch zu groß, gemeinsames Credential über mehrere Workflows |
| Sub-Workflow | Execute Workflow gibt nichts oder Fehler zurück | Parameter nicht übergeben, Rückgabewert nicht gesetzt, falsche Workflow-ID |
Ausdrucksfehler
Der größte Stolperstein: ={{ $json.field }} vs. {{ $json.field }}. Das führende = macht das Feld zu einem Ausdruck. Ohne wird der Literal-String {{ $json.field }} gesendet.
Prüfung:
- Klicke auf das Feld – wird der „Ausdruck“-Toggle (fx-Symbol) hervorgehoben? Wenn nicht, ist es der Literal-Modus.
- In der Code-Ansicht sollte der Wert mit
=beginnen:"value": "={{ $json.id }}"
Zugriff auf undefinierte Pfade: $json.customer.email wirft einen Fehler, wenn customer null ist. Verwende optional chaining: $json.customer?.email ?? 'unknown'.
Referenzierung vorheriger Nodes: Verwende $('Node Name').item.json.field, NICHT $node['Node Name'].json.field (veraltet). Zitiere den genauen Node-Namen inklusive Leerzeichen.
Häufige Ausdrucksmuster:
// Array-Zugriff
{{ $json.items[0].name }}
{{ $json.items?.[0]?.name ?? 'leer' }}
// Ausgabe vorheriger Nodes
{{ $('Webhook').item.json.body.email }}
// Alle Items von vorherigem Node (für Schleifen)
{{ $('Split In Batches').all().map(i => i.json.id) }}
// Bedingung
{{ $json.amount > 100 ? 'hoch' : 'niedrig' }}
// Datumsformatierung (n8n verwendet Luxon)
{{ $now.toISO() }}
{{ $now.minus({ days: 7 }).toFormat('yyyy-MM-dd') }}
// Umgebungsvariablen (selbst gehostet)
{{ $env.MEIN_GEHEIMNIS }}
Diagnose von Typkonflikten
n8n übergibt Daten als Array von Items, jedes mit { json: {...}, binary: {...} }. Viele Fehler entstehen, wenn ein einzelnes Item als Array behandelt wird oder umgekehrt.
Inspektionsroutine:
- Öffne die Eingabeansicht des fehlschlagenden Nodes (linkes Panel)
- Prüfe: Ist es EIN Item mit einem Array darin (
{ json: { list: [...] } }), oder mehrere Items ([ { json: {} }, { json: {} } ])? - Diese erfordern unterschiedliche Behandlung:
- Array-in-einem-Item → verwende
Item Lists→ „Split Out Items”, um aufzufächern - Bereits mehrere Items → arbeite pro Item
- Array-in-einem-Item → verwende
Split In Batches gibt auf dem Haupt- vs. „done“-Ausgang unterschiedliche Formen aus – der Hauptausgang ist ein Batch, der „done“-Ausgang ist leer. Schließe entsprechend an.
Stille Leere – die schlimmste Art
Workflow zeigt grüne Häkchen, aber es ist nichts passiert. Diagnosereihenfolge:
- Prüfe Aufbewahrung von Ausführungsdaten. Einstellungen → „Daten erfolgreicher Ausführungen speichern” muss während des Debuggens auf „Alle” stehen, nicht auf „Keine”.
- Inspiziere die Ausgabe jedes Nodes. Klicke auf jeden Node → „Ausgabe”-Panel. Finde den ersten Node, der leer ist, obwohl Du Daten erwartest.
- Pinned-Daten? Wenn ein Node ein Pin-Symbol hat, gibt er gepinnte Testdaten zurück, KEINE echten Daten. Rechtsklick → Daten entpinnen.
- Filter-/IF-Bedingungen. Eine
IF-Bedingung, die auf „falsch” ausgewertet wird, überspringt den Zweig stillschweigend. Überprüfe den Wert der Bedingung zur Laufzeit. - Credential-Bereich. Google-/Microsoft-OAuth-Credentials haben oft eingeschränkte Bereiche. Ein „Google Sheets”-Credential erlaubt nicht, Gmail zu lesen. Authentifiziere mit den korrekten Bereichen neu.
Authentifizierungsfehler
- 401 bei einem zuvor funktionierenden Workflow → Token abgelaufen. Authentifiziere das Credential neu.
- 401 sofort bei einem neuen Workflow → falscher Credential-Typ. Z.B. „Header Auth” vs. „OAuth2” – prüfe die API-Dokumentation.
- 403 mit gültigem Token → fehlender Bereich ODER falsches Konto. OAuth-Credentials sind pro Konto; bestätige, dass Du Dich mit dem richtigen Google-/Meta-Konto authentifiziert hast.
Selbst gehostetes n8n spezifisch: Wenn ein Credential nach einem Container-Neustart plötzlich nicht mehr funktioniert, überprüfe, ob der Verschlüsselungsschlüssel (N8N_ENCRYPTION_KEY env var) dauerhaft gespeichert ist. Verlust = alle Credentials sind beschädigt.
Rate-Limit-Fehler
Symptom: funktioniert bei 10 Items, schlägt bei 100 fehl. Klassiker.
Lösungsmuster:
- Wickle den API-Aufruf in
Split In Batchesmit einerbatchSize, die dem Limits pro Sekunde des Anbieters entspricht - Füge einen
Wait-Node zwischen Batches ein:waitBetweenBatches: ceil(60000 / requests_per_minute) - Setze
retry.maxTries: 3mitretry.waitBetweenTries: 5000im HTTP-Request-Node - Überprüfe Response-Header (
X-RateLimit-Remaining,Retry-After) und führe dynamisches Backoff über einenCode-Node durch
Bei cron-gesteuerten Workflows, die denselben Anbieter aus mehreren Cron-Jobs ansprechen, zentralisiere den API-Aufruf in EINEM Sub-Workflow mit einem Semaphore-Muster (MySQL-Zeile als Sperre).
Sub-Workflow-Fehler
Execute Workflow gibt am häufigsten null oder undefined zurück, weil:
- Der übergeordnete Workflow keine Daten übergeben hat. Überprüfe „Workflow-Inputs” im Execute-Workflow-Node – muss
{{ $json }}oder explizite Felder referenzieren. - Der untergeordnete Workflow keinen Ausgabewert gesetzt hat. Die Ausgabe des LETZTEN Nodes im Sub-Workflow wird zum Rückgabewert. Wenn der letzte Node ein
MySQL-Insert ist, das nichts zurückgibt, bekommt der übergeordnete Workflow nichts. Füge einen abschließendenSet-Node hinzu, der die Rückgabestruktur aufbaut. - Falsche Workflow-ID. Der Sub-Workflow wurde gelöscht und neu erstellt → neue ID → Referenz veraltet.
Lesen von n8n-Ausführungslogs
Das Ausführungslog zeigt Ein- und Ausgabe pro Node. Debug-Muster:
- Finde den ersten fehlschlagenden Node (rot).
- Betrachte SEINE Eingabe (links). Hat die Struktur das, was Du erwartet hast?
- Wenn die Eingabe falsch ist, liegt der Fehler VORGELAGERT – verfolge rückwärts.
- Wenn die Eingabe richtig ist, aber die Ausgabe falsch/fehlerhaft, liegt der Fehler IN DIESEM NODE – überprüfe die Parameter.
Die meisten Fehler sind vorgelagerte Strukturprobleme, die sich als nachgelagerte Fehler tarnen. Die Fehlermeldung lügt darüber, wo der Fehler tatsächlich sitzt.
Schnellkorrektur-Checkliste für häufige Fälle
- Ausdruck wird nicht interpretiert → führendes
=hinzufügen - Node sagt „Keine Items zum Verarbeiten” → vorgelagerter IF filtert alles weg, oder vorheriger Node gab nichts zurück
- Google Sheets Append fügt Duplikate ein → keine Unique-Constraint, füge Idempotenzprüfung hinzu (siehe
mysql-checkpointing-Skill) - LLM gibt Müll-JSON zurück → wechsle von rohem HTTP zu
Information Extractormit Schema (siehechain-llm-pattern-Skill) - Webhook läuft ab → verschiebe schwere Arbeit hinter
Respond to Webhook(zuerst antworten, dann asynchron verarbeiten)
Wenn Du nicht weiterkommst
Bitte den Benutzer um:
- Screenshot des Ausführungslogs (das rot umrandete Panel)
- Die genaue Fehlermeldung (Kopieren/Einfügen aus dem Node)
- Die Parameter des Nodes (Registerkarte „Einstellungen”, nach Möglichkeit JSON-Ansicht)
- Ob es jemals funktioniert hat (Regression vs. neuer Fehler)
Rate nicht ohne diese Informationen. n8n-Fehler sind spezifisch – vage Vermutungen verschwenden Zeit.