Wie fängt man Workflows ein, die einwandfrei laufen, aber nichts bewirken?

Wie erkennt man Workflows, die fehlerfrei laufen, aber nichts bewirken?

Ich führe seit einer Weile Client-Automatisierungen in n8n durch und stoße immer wieder auf denselben Fehler. Mich interessiert, wie alle anderen damit umgehen.
Der Workflow wird ausgeführt. Jeder Node ist grün. Keine Fehler geworfen. Und null Datensätze wurden tatsächlich verarbeitet.
Meistens ist es etwas Stilles vor: Ein Token ist abgelaufen, ein Feld wurde umbenannt, eine API hat ihre Response-Form geändert, oder ein Filter passt plötzlich auf nichts mehr. Der Error-Workflow wird nie ausgelöst, weil aus Sicht des Systems nichts schiefgegangen ist.
Das, was mich Zeit kostet, ist nicht die Behebung, sondern die Verzögerung. Bis das jemand bemerkt, ist der Workflow schon seit Tagen kaputt.
Vor allem für diejenigen unter euch, die Workflows für Clients betreiben:
• Überprüft ihr noch etwas über den Error-Workflow hinaus?
• Hat jemand dafür etwas Externes angebunden (Healthchecks.io, Cron-Pings, einen benutzerdefinierten Heartbeat-Node)?
• Validiert ihr Datensatzzahlen, oder nur, dass der Durchlauf abgeschlossen ist?
• Oder, ehrlich gesagt: Erfahrt ihr es normalerweise, wenn der Client euch Bescheid gibt?
Das Letzte ist das, das ich verhindern möchte. Mich interessiert, was bei den Leuten tatsächlich funktioniert.

Hey @rodri.galloswork, während du auf eine Antwort wartest, sind hier einige Dinge, die dir helfen könnten:

Empfohlene Ressourcen

Automatisch zu deiner Frage zugeordnet.

Dokumentation:

Forum:

@ShawnWilliams, @Dan_Westness, @Niffzy - ihr habt bei ähnlichen Problemen schon geholfen, könnt ihr einen Blick drauf werfen?

Automatisch vorgeschlagen vom Community-Bot von n8n. Es ist ein Pilotprogramm - bitte gib hier Feedback.

Ja—die nützliche Unterscheidung ist die Ausführungsgesundheit versus Ergebnisgesundheit. Ich teile sie normalerweise in drei Checks auf:

  1. Ausführungsgesundheit: Start/Ende, Dauer, Wiederholungen, Upstream-Status und der Ausführungsfehlerpfad.
  2. Ausgabegesundheit: erwartetes Zählfenster, Aktualität, erforderliche Felder, Schema-Hash und Duplikat-Schlüssel-Checks.
  3. Quittungsgesundheit: eine Downstream-Datensatz-ID, Bestätigung oder ein expliziter Exceptioneintrag.

Eine grüne Ausführung mit einem unerwarteten Null sollte zur Überprüfung anstatt als Erfolg markiert werden. Bewahren Sie die rohen Ausführungsnachweise auf und setzen Sie Alerts bei aufeinanderfolgenden Fehlversuchen, damit ein legitimes leeres Ergebnis keinen Lärm verursacht.

Ich habe die Grenze in ein kleines synthetisches Labor hier gelegt: n8n Silent Success Lab | Romeo Apps

Es sind RomeoApps-eigene Fixture-Daten, keine Client-Telemetrie, und es werden keine Anmeldeinformationen verwendet. Bei einem echten Workflow sind normalerweise eine redigierte Ausführung, das erwartete Ausgabefenster und die Zielbestätigung ausreichend, um den ersten fehlenden Check zu identifizieren.

Gute Aufschlüsselung oben zu Ausführungs- vs. Output- vs. Quittungs-Gesundheit. Auf der praktischen n8n-Seite ist hier ein leichtgewichtiges Muster, das dies ohne zusätzliche Infrastruktur erfasst:

  • Ein Error Trigger-Workflow allein hilft hier nicht — er wird nur bei unbehandelten Ausnahmen ausgelöst, und dein Problem ist genau der Fall, in dem nichts wirft.
  • Beende deinen Hauptworkflow mit einem IF-Node, der die tatsächliche Elementanzahl (oder ein bestimmtes Feld) überprüft, die aus dem letzten “echten” Node kommt. Wenn sie 0 ist oder nicht mit deinen Erwartungen übereinstimmt, leite sie in einen Stop and Error-Node — das zwingt n8n, ein leeres/falsches Ergebnis als Fehler zu behandeln, der dann doch deinen Error-Workflow / deine Benachrichtigung auslöst.
  • Für das “tagelang stumm”-Problem speziell, funktioniert ein separater Schedule Trigger-Heartbeat-Workflow gut: Alle N Minuten/Stunden überprüft er (HTTP Request oder eine DB-Abfrage), ob der erwartete nachgelagerte Datensatz kürzlich erstellt wurde, und warnt dich, wenn nicht.
  • Platziere die Datensatzanzahl-Überprüfung so nah wie möglich am eigentlichen Write-Node (direkt nach dem Kintone/DB/API-Write), nicht am sehr Ende des Workflows — so erfasst du es, bevor andere Branches mit schlechten Daten weiterarbeiten.

Das Muster, das mir am meisten geholfen hat: Lass niemals “Workflow ohne Fehler beendet” dein einziges Erfolgssignal sein — füge immer einen expliziten Assertions-Node hinzu, bevor der Workflow grün enden darf.

Hallo @rodri.galloswork

Das ist ein bekanntes und wichtiges Problem. Wie andere bereits gesagt haben, musst du zwischen einem Workflow unterscheiden, der fehlschlägt, und einem Workflow, der erfolgreich ausgeführt wird, aber nichts produziert. Du kannst dich im zweiten Fall nicht einfach auf den integrierten Fehler-Workflow verlassen.

Du kannst am Ende deines Flows eine Assertion-Prüfung hinzufügen, aber ich bevorzuge eine „Gatekeeper"-Prüfung gleich am Anfang. Das ist effizienter, weil es den Rest deines Workflows stoppt, wenn es keine Daten zu verarbeiten gibt.

Das Muster ist einfach:

  • Füge nach deiner Hauptabfrage (z. B. „Get Records from DB

Das ist solide, besonders der Teil über die Platzierung der Count-Prüfung direkt nach dem Write-Node und nicht am Ende. Das ist ein Fehler, den ich oft sehe, wo Leute zu spät prüfen und schlechte Daten bereits downstream propagiert haben

Der separate Heartbeat-Workflow-Ansatz ist im Grunde das, worauf ich auch gestoßen bin, als ich das gebaut habe. Das Teil, das bei Skalierung knifflig wird, ist die Verwaltung eines solchen Workflows pro Client. Wenn du bei 15 oder 20 Automationen über verschiedene Clients hinweg ankommst, frisst das manuelle Heartbeat-Setup echte Zeit auf. Das war der Haupttreiber für mich, etwas zu bauen, das das außerhalb des Workflows selbst handhabt

Der Gatekeeper am Anfang ist clever, daran hätte ich nicht gedacht. Er stoppt die ganze Chain, damit sie nicht mit leeren Daten läuft, anstatt sie durchzulassen und am Ende zu prüfen. Definitiv effizienter.

Eines kommt mir mit diesem Pattern aber immer wieder unter, es funktioniert super pro Workflow, löst aber den „Workflow ist komplett aufgehört zu laufen

Zum Punkt „ein Herzschlag pro Client-Workflow skaliert nicht

Count == 0 fängt die laute Version davon ab. Die, die uns härter getroffen hat, ist count > 0 aber falsch: N Zeilen landen, die Assertion besteht, und jede einzelne hat einen Null-Wert in dem Feld, das wichtig war, weil ein vorgelagertes Feld umbenannt wurde und dein Write-Node die Zeile trotzdem akzeptiert hat. Nichts in diesem IF-Node-on-Count-Muster dieses Threads fängt das ab, weil es die Kardinalität prüft, nicht die Form.

Die Behebung hat die gleiche Form eines Nodes, just mit einer anderen Assertion: Nach dem Write prüfe, ob die zwei oder drei Felder, auf die du tatsächlich angewiesen bist, nicht null und ungefähr vom richtigen Typ sind – nicht, dass die Itemanzahl ungleich null ist. Kostet eine Bedingung mehr auf dem gleichen IF-Node, den nathan3 bereits beschrieben hat, und es fängt den Fehlermodus ab, bei dem eine Umbenennung oder eine API-Kontraktänderung die Daten verschlechtert, anstatt sie zu nullen, was in meiner Erfahrung der häufigere Weg ist, auf dem eine Schemaänderung tatsächlich etwas bricht.

Eine Sache mehr, die sich lohnt, wenn du für diese Läufe abrechnest oder rechnest: Leite die gleiche Assertion in das ein, was entscheidet „hat dieser Lauf gezählt

Der Punkt von themineworks ist derjenige, den ich unterstreichen würde: Count ist Kardinalität, nicht Korrektheit, und der Fehler, der dich tatsächlich kostet, ist N Zeilen, die dort landen, wo das Feld, auf das du angewiesen bist, null ist, oder schlimmer noch, vorhanden und plausibel, aber falsch. Ein Feld wird upstream umbenannt, dein Write-Node akzeptiert die Zeile immer noch, und jetzt hast du echte Daten, die stillschweigend falsch sind. Null- und Typ-Assertions fangen die Version ab, in der es zu leer degradiert. Sie fangen nicht die Version ab, in der es zu etwas Plausiblem, Nicht-Null, vom richtigen Typ und einfach Falschem degradiert, weil an der Zeile nichts falsch aussieht.

Die einzige Überprüfung, die das erfasst, ist ein Canary mit bekannter Antwort. Schieb neben dem echten Traffic eine Handvoll synthetischer Eingaben durch, deren korrekte Ausgabe du vorher aufgeschrieben hast, führe sie end-to-end durch die Live-Pipeline nach einem Zeitplan aus, und überprüfe, dass die Ausgabe der bekannten Antwort entspricht, nicht nur dass sie die richtige Form hat. Wenn eine Zuordnung stillschweigend auf ein falsches, aber gültiges Feld zeigt, stimmt der erwartete Wert des Canary nicht mehr überein und du erhältst am selben Tag einen lauten Fehler, weil du gegen Wahrheit vergleichst und nicht gegen Plausibilität.

Es schließt auch die Lücke, die Cam angesprochen hat. Ein Canary, der nicht meldet, ist selbst der Alert, sodass der gleiche Mechanismus sowohl die Pipeline, die verstummt, als auch die Werte, die subtil falsch werden, erfasst, mit einer externen Überprüfung, die auf das Canary-Ergebnis wartet, statt eines Heartbeats pro Workflow. In der Praxis verwende ich drei Schichten: Count und Null- oder Typ-Assertions direkt nach dem Write für die lauten Fehler, Volume-Wasserzeichen für das langsame Auslaufen, und einen geplanten Canary mit bekannter Antwort für den plausiblen, aber falschen Fall, den die ersten beiden strukturell nicht sehen können.

Der Fall count > 0, aber wrong-shape ist derjenige, um den ich mir auch Sorgen machen würde.

Ein nützliches Muster ist es, die finale „Erfolgsprüfung

@rodri.galloswork Du hast erwähnt, dass das Verwalten von Heartbeats pro Workflow bei 15–20 Automationen über Clients hinweg echte Zeit aufzehrt, und dass dich das dazu treibt, etwas außerhalb der Workflows zu bauen. Das ist auch etwas, das ich mir anschaue..(Ich bin Entwickler und lerne, bevor ich mich entscheide, ob ich es baue).

Letztes Mal, als ein Client-Workflow grün war, aber nichts gemacht hat – wie lange war er kaputt, bevor jemand es bemerkte, und wer hat es zuerst bemerkt, du oder der Client?
Was müsste „außerhalb des Workflows handhaben

Etwas bei 2.36.7 gefunden, das ich anders angenommen hatte.

Wenn eine IF-Bedingung nicht mehr erfüllt ist, wird der Node auf diesem Zweig nicht als übersprungen markiert. Er ist überhaupt nicht in runData vorhanden. Die Ausführung gibt trotzdem status: success zurück.

Wenn du also Nodes durchiterierst und nach einem schlechten Status suchst, findest du nichts. Das Signal ist ein Schlüssel, der nicht vorhanden ist.

Repro: Schedule-Trigger, Code-Node mit Ausgabezeilen, IF, das nie erfüllt sein kann, Code-Node auf dem true-Zweig. Dieser letzte Node fehlt einfach.

Alles in diesem Thread zeigt dir, wann ein Durchlauf schiefgegangen ist. Es gibt einen Schritt davor, den niemand erwähnt hat, und dieser ist speziell auf das Problem mit 15–20 Automatisierungen ausgerichtet: Du kannst herausfinden, welche deiner Workflows überhaupt zu diesem Fehler fähig sind, indem du die Workflow-JSON liest, bevor du irgendeinen von ihnen instrumentierst.

Die Assertion-Muster oben sind richtig. Aber jedes kostet einen Node und eine Beurteilung pro Workflow, und bei 20 Workflows über verschiedene Clients hinweg ist genau das der Teil, der die Zeit aufzehrt. Die nützliche Frage wird also: Welche bekommen die Assertion zuerst?

Das ist aus der Datei beantwortbar. Für jeden Node, der etwas außerhalb von n8n schreibt — Datenbank, Sheets, CRM, Slack, beliebige HTTP POST/PUT/DELETE — prüfe, ob es einen Pfad vom Trigger zum Ende des Workflows gibt, der das Ende erreicht, ohne diesen Node zu durchlaufen. Ein IF ohne etwas im falschen Branch, ein Switch ohne Fallback, ein Filter, der die Item-Liste leeren kann: Jeder gibt dir einen Durchlauf, der normal endet und nichts schreibt. Diese Workflows sind es, wo CameronDWills’ Check-in-Node und nathans Assertion ihr Geld verdienen. Workflows, bei denen jedes Schreiben auf jedem Pfad sitzt, können warten.

Von Hand dauert es ein paar Minuten pro Workflow: Liste die Schreibvorgänge auf, verfolge zurück zum Trigger, frage dich, ob dieser Durchlauf immer noch erfolgreich ausgesehen hätte.

Ich habe diese Prüfung über 2.043 öffentliche n8n-Vorlagen durchgeführt. 13,5% hatten mindestens einen Fall mit hohem Schweregrad — einen Schreibvorgang, der übersprungen werden kann, während der Durchlauf immer noch Erfolg meldet. Vorlagen sind kuratiert und poliert, daher würde ich das eher als Untergrenze als als Durchschnitt lesen.

Eine Gegenfrage, da du derjenige bist, der damit lebt: Wenn ein Client-Workflow verstummt, besteht die Verzögerung hauptsächlich darin, nicht zu wissen, dass etwas kaputt ist, oder nicht zu wissen, welchen der zwanzig man zuerst öffnen soll? Ich bin vom zweiten ausgegangen und möchte gerne wissen, ob das falsch ist.

Offenlegung: Ich habe eine kostenlose Seite erstellt, die diese Prüfung durchführt — füge die Workflow-JSON ein und sie zeigt die Schreibvorgänge auf, die übersprungen werden können. Keine Anmeldung erforderlich, im Browser geparst, sodass die JSON die Seite nie verlässt: https://stillrunning.dev. Ich helfe gerne hier stattdessen bei einem Workflow weiter, wenn du ihn lieber nirgendwo anders einfügen möchtest.

Ich denke, du bist damit pretty much covered, aber hier ist meine Vorgehensweise.

Ich habe ein systematisches Error-Handling-Protokoll

  1. Richte einen Error-Workflow ein → das ist das absolute letzte Mittel für den Fall, dass alles andere fehlschlägt, und er sollte Folgendes tun:
    1. Den Error protokollieren
    2. Die Personen oder dich benachrichtigen
    3. (optional, aber trotzdem nützlich) Falls es sich um einen Webhook-Workflow handelt, kannst du einfach die Payload an deine Error-DB anhängen und hast einen Button zum erneuten Senden an den Webhook; das spart dir Zeit, da du nicht zu den Ausführungen gehen, die Workflows öffnen usw. musst; es führt den Workflow von dort aus erneut aus, vorausgesetzt du hast Idempotency Keys und es ist ein transienter Fehler.
  2. Verwende einen guten Idempotency Key
  3. Workflow-Level-Error
    1. Richte ein Payload-Validierungssystem ein; dieses sollte die meisten deiner Probleme bei leeren Daten lösen.
      1. Richte eine initiale Payload-Validierung ein
      2. Richte eine abschließende Payload-Validierung vor dem Schreibvorgang ein
    2. Verwende niemals Filter; nutze stattdessen IF-Knoten mit strikter Bedingungsvalidierung und einen Stop- und Error-Node-Pfad für alles, das diesen Bedingungen nicht entspricht
      1. :white_check_mark: Dies ermöglicht es dir, von Anfang an ein sehr striktes Protokoll zu gewährleisten; alles, das nicht in diesen Bedingungen liegt, wird als Error geworfen. Du kannst dann proaktiv vorgehen und die Bedingungen im Laufe der Zeit erweitern.
  4. Node-Level-Errors
    1. Deaktiviere „Continue on Fail"
    2. Verwende „Retry on Fail"
    3. In einigen spezifischen Fällen (obwohl sehr selten), verwende den Error-Pfad.
  5. Field-Level-Validierung
    1. Verarbeite Daten bei Ankunft, konvertiere oder bereinige je nach eingegangenen Daten
    2. Verwende Fallback-Werte wo nötig: null, undefined und andere

Ich habe normalerweise eine Monitoring-DB mit einem zugewiesenen Status; du kannst dies entweder als Teil der Daten haben, die du verarbeitest (der Workflow-Prozess führt an, und Leads haben bereits einen Status)

ODER du stellst ihn manuell ein, besonders wenn du proaktiv vorgehen möchtest, während du diese Fehler permanent behebst, indem du den Run mit dem Status „started

@CameronDWills’s invertierte Version hat die richtige Form. Das Einzige, das ich hinzufügen würde, ist etwas über die Tabelle, von der sie abhängt.

Jedes Muster in diesem Thread — Check-in-Knoten, Assertions, Canaries — erfordert, dass der Workflow kooperiert. Du fügst einen Knoten hinzu oder schreibst eine Erwartung auf. Das ist in Ordnung, wenn du das Ding gebaut hast. Es wird zum Problem in den zwei Fällen, die tatsächlich weh tun: Workflows, die du geerbt hast, und Client-Instanzen, bei denen du nicht frei bist, 20 Pipelines zu bearbeiten, bevor du weißt, welche wichtig sind.

Es gibt ein Signal, das du von außen bekommen kannst, ohne etwas zu berühren. Der Executions-Endpoint gibt dir pro Workflow an, wann jeder Durchlauf begonnen hat und wie er geendet hat. Zwei Dinge ergeben sich aus dieser Historie:

Kadenz. Sortiere die Executions eines Workflows und nimm die mediane Lücke. Das ist die Erwartung — du schreibst nicht manuell max_silence_minutes pro Pipeline auf, was bei 20 Workflows über Clients hinweg das gleiche Skalierungsproblem in neuem Gewand ist. Ein Workflow, der einen Monat lang stündlich lief und seit sechs Monaten nicht mehr läuft, ist der Fall „Trigger hat aufgehört zu feuern

Es gibt eine Unterscheidung in diesem Thread, die ich für wert halte, sie herauszuarbeiten, weil die Lösungen unterschiedlich sind.

Fast alles oben behandelt einen Workflow, der früher funktioniert hat und stillschweigend nicht mehr funktioniert — ein Token ist abgelaufen, ein Feld wurde umbenannt, eine Response-Form hat sich geändert. Die Count-Assertions und der Heartbeat-Workflow sind die richtige Antwort darauf.

Die andere Hälfte dieses Problems sind Workflows, die von Anfang an nie funktioniert haben und trotzdem Erfolg gemeldet haben.

Ich habe kürzlich fünf meiner eigenen Workflows zum ersten Mal ordnungsgemäß ausgeführt — gegen einen lokalen Server, der die APIs vertritt, und habe jeden ausgehenden Request-Body protokolliert. Alle fünf waren fehlerhaft, und alle waren grün:

  • Ein HTTP-Request-Node (typeVersion 4.2, contentType json) mit der Payload im body-Parameter statt in jsonBody. Dieser Node liest jsonBody, also was tatsächlich die Maschine verließ, war {"":""}. Der Endpoint antwortete mit 200. Jeder Node grün.

  • Prompt-Text in einem Set-Node gespeichert ohne führendes =, also evaluierte n8n ihn nie. Das Modell erhielt die Literalzeichen {{ $json.article_text }} und antwortete trotzdem, erzeugte eine perfekt plausible Antwort aus dem Nichts.

  • Ein Parse-Schritt, der eine API-Response über das Item verbreitete, das es bereicherte, und die ursprünglichen Felder überschrieb. Alles Nachgelagerte lief fröhlich auf dem falschen Objekt.

Keines davon wirft einen Fehler. Eine Item-Count-Prüfung fängt sie auch nicht, weil die Counts alle korrekt sind — ein Item rein, ein Item raus, bei jedem Schritt. Was falsch ist, ist der Inhalt dessen, was gesendet wurde, und nichts in der Execution-View zeigt dir das, es sei denn, du öffnest den Node und liest ihn.

Das Einzige, das sie fand, war, jede Integration auf einen lokalen Server zu richten, der den Request-Body protokolliert, den Workflow einmal auszuführen und das Log zu lesen. Zwanzig Minuten zum Einrichten, und es hat in jedem Workflow, den ich seitdem darauf gerichtet habe, etwas gefunden.

Also neben „ist die Count das, was ich erwarte

Der Beitrag von @enzosoftware ist derjenige, auf dem ich aufbauen würde, denn „habe ich mir eigentlich schon angesehen, was das sendet?

Sealed Replay mit blockiertem Egress hat die richtige Form, und die Raw-Bytes-Regel ist der Teil, den ich unterstreichen würde. Ein zusammengefasstes Log des Empty-Body-Falls sieht identisch mit einem gesunden aus, also wenn die Aufzeichnung das wegwirft, beweist das Replay nichts.

Es gibt eine Hälfte, die ich hinzufügen würde, und sie sitzt genau nach dem Punkt, wo dein Replay grün wird.

Ich habe neun Mängel über fünf Workflows behoben, jeden gegen den lokalen Logging-Server neu ausgeführt und die erfassten Bodies gegen das verglichen, was ich erwartet habe. Alle neun kamen korrekt zurück. Der Fix war real.

Einer dieser Workflows war als herunterladbare Datei zum Verkauf. Jeder, der ihn gekauft hätte, hätte immer noch die fehlerhafte Version bekommen, weil sich das, was ich verifiziert hatte, und das, was übergeben wurde, stillschweigend auseinander entwickelt hatten. Ich fand es nur heraus, indem ich mein eigenes Produkt herunterladete, wie ein Kunde es würde, und die Bytes gegen die Datei, die ich gebaut hatte, überprüfte. Sie stimmten nicht überein.

Also beantwortete das Replay „dreht dieser Fix diesen aufgezeichneten Fehler in die richtige Ausgabe um?" Es konnte nicht beantworten: „Ist der Fix in dem Artefakt, das jeder tatsächlich erhält?" Für einen Workflow, den du selbst ausführst, sind das dieselbe Frage. Sobald es einen Export, einen Deploy-Schritt, einen Template-Import oder eine Datei gibt, die jemand herunterlädt, fallen sie auseinander, und die Lücke ist genau so still wie der ursprüngliche Bug.

Die Überprüfung, die sie schließt, ist langweilig. Hole das Artefakt so, wie der Empfänger es erhält, nicht so, wie du es gebaut hast, und replay davon. Wenn es eine Datei ist, hash sie. Wenn es ein Import ist, importiere es in eine saubere Instanz und führe das sealed Replay gegen das aus, was auf der anderen Seite herauskommt.

Die Fehlerklasse, die du beschreibst, ist grün bedeutet nicht funktionierend. Das ist dieselbe Klasse einen Schritt weiter draußen. Behoben bedeutet nicht versendet.

CameronDWills’ Expectations-Tabelle ist der Teil, auf dem ich aufbauen würde, denn „das sollte mindestens stündlich laufen und mindestens einen Datensatz liefern