Skip to content

Technik Blog

IoT, Smart Home & Mikrocontroller einfach erklärt

Menu
  • Smarthome
  • Gartenautomation
  • Mikrocontroller
    • Arduino
    • ESP32 & Co.
    • Calliope Mini
    • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
Menu

Node-RED debuggen: JavaScript-Fehler, Logs und Speicherprobleme finden

Veröffentlicht am 24. Oktober 202624. Oktober 2026 von Stefan Draeger

Node-RED macht es sehr einfach, Abläufe visuell zusammenzubauen und eigene Logik mit JavaScript in Function-Nodes zu ergänzen. Solange ein Flow funktioniert, ist das angenehm unkompliziert. Spannend wird es meistens erst dann, wenn plötzlich Werte fehlen, ein Function-Node nicht das erwartete Ergebnis liefert, Fehlermeldungen im Log auftauchen oder der Speicherverbrauch von Node-RED immer weiter ansteigt.

Dann reicht es oft nicht mehr aus, nur auf den Flow zu schauen. Stattdessen muss man Schritt für Schritt herausfinden, welche Daten tatsächlich durch die Nodes laufen, an welcher Stelle der JavaScript-Code nicht wie erwartet arbeitet und ob möglicherweise ein tieferliegendes Problem im Node-RED- beziehungsweise Node.js-Prozess vorliegt.

Node-RED bringt dafür bereits einige hilfreiche Möglichkeiten mit. Dazu gehören unter anderem der Debug-Node, Ausgaben direkt aus Function-Nodes, die System-Logs sowie verschiedene Werkzeuge von Node.js zur Analyse von Speicherproblemen.

In diesem Beitrag zeige ich dir, wie du Node-RED systematisch debuggen kannst. Wir beginnen mit einfachen JavaScript-Fehlern in Function-Nodes, schauen uns anschließend die Logs von Node-RED an und gehen zum Schluss einen Schritt tiefer, indem wir Speicherprobleme mit Heap Snapshots untersuchen.

Dabei geht es nicht darum, einfach möglichst viele Debug-Ausgaben einzubauen. Ziel ist vielmehr, Fehler gezielt einzugrenzen und nachvollziehen zu können, was innerhalb eines Flows und im Hintergrund von Node-RED tatsächlich passiert.

Inhaltsverzeichnis

  • Passende Beiträge zum Thema
  • Was bedeutet Debugging in Node-RED?
  • Nachrichten im Flow prüfen
    • Die komplette Nachricht mit dem Debug-Node anzeigen
    • Erst die Nachricht prüfen, dann den Code
  • Variablen direkt in der Function Node prüfen
    • Nicht nur den Wert, sondern auch den Datentyp prüfen
    • Mehrere Werte gemeinsam ausgeben
  • Wo bricht mein JavaScript-Code ab?
    • Fehler mit mehreren Debug-Ausgaben eingrenzen
    • Den problematischen Wert direkt prüfen
  • Node-RED-Logs prüfen
    • Variante 1: Node-RED direkt im Terminal gestartet
    • Variante 2: Node-RED als systemd-Service
    • Variante 3: Node-RED im Docker-Container
    • Gezielt nach Fehlern suchen
  • Node-RED-Logs für einen neuen Test sichern und übersichtlich halten
    • Variante 1: Node-RED als systemd-Service
    • Variante 2: Node-RED im Docker-Container
    • Speicherprobleme in Node-RED erkennen
  • Speicherverbrauch beobachten
    • Speicherinformationen mit dem V8-Modul auslesen
    • Werte regelmäßig protokollieren
    • Das Stundenminimum beobachten
    • Ein steigender Heap ist nicht automatisch ein Memory Leak
  • Fazit

Passende Beiträge zum Thema

Einige Grundlagen rund um die Fehlersuche und das Logging in Node-RED habe ich bereits in separaten Beiträgen ausführlich behandelt. Damit dieser Beitrag nicht unnötig lang wird, werde ich diese Themen hier teilweise nur kurz aufgreifen.

Wenn du tiefer einsteigen möchtest, findest du weitere Informationen in diesen Beiträgen:

  • Node-RED Debugging ohne Debug Node: Meldungen direkt aus der Function Node
    Hier zeige ich dir, wie du mit node.debug(), node.warn() und node.error() Meldungen direkt aus deinem JavaScript-Code heraus erzeugen kannst.
  • Node-RED Fehler finden: Catch-, Status- und Debug-Node einfach erklärt
    In diesem Beitrag geht es um die klassischen Werkzeuge zur Fehlersuche innerhalb eines Flows und darum, wie du Fehler und Statusänderungen gezielt abfangen kannst.
  • Node-RED Fehler loggen: Mit Bordmitteln und eigener Logger-Node
    Wenn Fehler nicht nur im Debug-Bereich erscheinen, sondern dauerhaft gespeichert werden sollen, findest du hier verschiedene Möglichkeiten zum Aufbau eines eigenen Loggings.
  • Node-RED Context nach Neustart behalten – so geht’s
    Context-Werte liegen standardmäßig im Arbeitsspeicher von Node-RED. In diesem Beitrag zeige ich dir, wie der Context funktioniert und wie sich Werte bei Bedarf dauerhaft speichern lassen.

Was bedeutet Debugging in Node-RED?

Beim Debuggen von Node-RED geht es nicht nur darum, eine Fehlermeldung im Debug-Fenster zu finden. Je nach Problem muss man an unterschiedlichen Stellen ansetzen.

Grundsätzlich lassen sich drei Ebenen unterscheiden:

  • Daten im Flow: Kommen die erwarteten Werte überhaupt am richtigen Node an?
  • JavaScript-Code: Verarbeitet eine Function Node die Daten korrekt oder tritt innerhalb des Codes ein Fehler auf?
  • Node-RED beziehungsweise Node.js: Gibt es Probleme, die nicht direkt im Flow sichtbar werden, beispielsweise Fehlermeldungen im System-Log oder einen stetig steigenden Speicherverbrauch?

Gerade bei größeren Flows ist es hilfreich, diese Ebenen getrennt voneinander zu betrachten. Wenn beispielsweise eine Function Node nicht das erwartete Ergebnis liefert, bedeutet das nicht automatisch, dass der JavaScript-Code fehlerhaft ist. Oft enthält bereits die eingehende Nachricht andere Daten als erwartet.

Anders sieht es bei Problemen aus, die erst nach mehreren Stunden oder Tagen auftreten. Wenn Node-RED beispielsweise immer mehr Arbeitsspeicher benötigt oder plötzlich neu startet, reicht die normale Debug-Seitenleiste meist nicht mehr aus. Dann müssen wir einen Blick auf die Logs und gegebenenfalls direkt auf den Speicher des Node.js-Prozesses werfen.

Wir beginnen deshalb zunächst mit der einfachsten Ebene: den Daten, die durch unseren Flow laufen.

Nachrichten im Flow prüfen

Bevor wir uns auf die Suche nach einem Fehler im JavaScript-Code machen, sollten wir zuerst prüfen, welche Daten überhaupt durch unseren Flow laufen.

Dafür reicht ein sehr einfacher Aufbau:

einfacher Node-RED Flow zum auswerten einer Temperatur
einfacher Node-RED Flow zum auswerten einer Temperatur
Node-RED Flow im JSON-Format
[
    {
        "id": "f6f2187d.f17ca8",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": ""
    },
    {
        "id": "inject_temp",
        "type": "inject",
        "z": "f6f2187d.f17ca8",
        "name": "Temperatur senden",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "",
        "topic": "",
        "payload": "23",
        "payloadType": "num",
        "x": 150,
        "y": 60,
        "wires": [
            [
                "function_error"
            ]
        ]
    },
    {
        "id": "function_error",
        "type": "function",
        "z": "f6f2187d.f17ca8",
        "name": "Temperatur auswerten",
        "func": "const temperatur = msg.payload.temperature;\n\nif (temperatur > 25) {\n    msg.status = \"warm\";\n} else {\n    msg.status = \"kühl\";\n}\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 380,
        "y": 60,
        "wires": [
            [
                "debug_output"
            ]
        ]
    },
    {
        "id": "debug_output",
        "type": "debug",
        "z": "f6f2187d.f17ca8",
        "name": "Ausgabe",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 610,
        "y": 60,
        "wires": []
    }
]

Der Inject-Node sendet in unserem Beispiel die Zahl 23 als msg.payload.

Die Function Node enthält folgenden Code:

const temperatur = msg.payload.temperature;

if (temperatur > 25) {
    msg.status = "warm";
} else {
    msg.status = "kühl";
}

return msg;

Auf den ersten Blick sieht der Code recht unspektakulär aus. Das Problem liegt allerdings bereits in der ersten Zeile:

const temperatur = msg.payload.temperature;

Der Code erwartet, dass sich innerhalb von msg.payload ein Objekt mit der Eigenschaft temperature befindet.

Also beispielsweise:

{
    "temperature": 23
}

Unser Inject-Node sendet aber lediglich: 23

Injection Node mit Payload als Zahl
Injection Node mit Payload als Zahl

Die Struktur der eingehenden Nachricht entspricht somit nicht dem, was unser JavaScript-Code erwartet.

Die komplette Nachricht mit dem Debug-Node anzeigen

Genau an dieser Stelle ist der Debug-Node eines der wichtigsten Werkzeuge in Node-RED.

Standardmäßig wird häufig nur msg.payload ausgegeben. Für die Fehlersuche lohnt es sich jedoch, im Debug-Node die Ausgabe auf die komplette Nachricht umzustellen.

Dadurch sehen wir nicht nur den Payload, sondern beispielsweise auch weitere Eigenschaften wie:

msg.payload
msg.topic
msg._msgid

und alle zusätzlichen Werte, die vorherige Nodes der Nachricht hinzugefügt haben.

Bei unserem kleinen Beispiel erkennen wir dadurch sofort:

msg.payload : number
23

Damit ist klar, dass msg.payload kein Objekt mit einer Eigenschaft temperature enthält.

Debugausgabe der kompletten Nachricht
Debugausgabe der kompletten Nachricht

Erst die Nachricht prüfen, dann den Code

Gerade bei Function Nodes passiert es schnell, dass man den Fehler direkt im JavaScript-Code sucht. Häufig liegt die Ursache aber bereits davor.

Ein vorheriger Node kann beispielsweise:

  • einen String statt einer Zahl liefern,
  • ein Objekt anders strukturieren als erwartet,
  • eine Eigenschaft gar nicht setzen,
  • null oder undefined weitergeben,
  • oder einen komplett anderen Payload erzeugen.

Deshalb ist es sinnvoll, beim Debuggen zuerst zu kontrollieren, welche Nachricht tatsächlich an der Function Node ankommt.

In unserem Beispiel müsste der Inject-Node statt der einfachen Zahl 23 beispielsweise folgendes Objekt senden:

{
    "temperature": 23
}

Dann kann die Function Node auf

msg.payload.temperature

zugreifen und den Wert korrekt verarbeiten.

Der erste Schritt beim Debugging sollte daher immer sein:

Stimmt die tatsächliche Struktur der Nachricht mit der Struktur überein, die mein JavaScript-Code erwartet?

Variablen direkt in der Function Node prüfen

Wenn die eingehende Nachricht korrekt aussieht, der Function Node aber trotzdem nicht das erwartete Ergebnis liefert, lohnt sich ein Blick direkt in den JavaScript-Code.

Dafür können wir uns einzelne Werte während der Verarbeitung ausgeben lassen.

Eine einfache Möglichkeit ist node.warn():

const temperatur = msg.payload.temperature;

node.warn(temperatur);

if (temperatur > 25) {
    msg.status = "warm";
} else {
    msg.status = "kühl";
}

return msg;

Der Wert von temperatur erscheint anschließend direkt in der Debug-Seitenleiste von Node-RED.

Gerade bei etwas längeren Function Nodes lässt sich damit schnell herausfinden, ob eine Variable tatsächlich den erwarteten Inhalt besitzt.

Nicht nur den Wert, sondern auch den Datentyp prüfen

Ein häufiger Fehler in JavaScript entsteht dadurch, dass ein Wert zwar richtig aussieht, aber den falschen Datentyp besitzt.

Beispielsweise können diese beiden Werte auf den ersten Blick identisch wirken: 23 und: "23"

Der erste Wert ist eine Zahl, der zweite ein String.

Mit typeof können wir den Datentyp direkt prüfen:

const temperatur = msg.payload.temperature;

node.warn({
    wert: temperatur,
    typ: typeof temperatur
});

return msg;

In der Debug-Seitenleiste sehen wir dann beispielsweise:

wert: 23
typ: "number"
Ausgabe eines Wertes mit node.warn() und dem Typ number
Ausgabe eines Wertes mit node.warn() und dem Typ number

Oder bei einem String:

wert: "23"
typ: "string"
Ausgabe eines Wertes mit node.warn() und dem Typ string
Ausgabe eines Wertes mit node.warn() und dem Typ string

Das ist besonders hilfreich, wenn Werte aus MQTT, HTTP-Anfragen, Formularen oder anderen Nodes stammen und nicht sofort klar ist, in welchem Datentyp sie weitergegeben werden.

Mehrere Werte gemeinsam ausgeben

Statt viele einzelne Debug-Ausgaben zu erzeugen, können wir auch mehrere Informationen in einem Objekt zusammenfassen:

node.warn({
    payload: msg.payload,
    temperatur: msg.payload?.temperature,
    typPayload: typeof msg.payload,
    typTemperatur: typeof msg.payload?.temperature
});

Dadurch erhalten wir auf einen Blick mehrere Informationen über den aktuellen Zustand unserer Nachricht.

Informationen zu einem Objekt zusammengefasst in einer Ausgabe
Informationen zu einem Objekt zusammengefasst in einer Ausgabe

Gerade beim Debuggen längerer Function Nodes ist diese Variante meist übersichtlicher als mehrere einzelne node.warn()-Aufrufe.

Ausführlicher habe ich das Debugging direkt aus einer Function Node bereits in meinem Beitrag „Node-RED Debugging ohne Debug Node: Meldungen direkt aus der Function Node“ beschrieben. Hier soll uns node.warn() vor allem dabei helfen, gezielt einzelne Variablen und Datentypen zu kontrollieren.

Wo bricht mein JavaScript-Code ab?

Bei längeren Function Nodes ist nicht immer sofort ersichtlich, an welcher Stelle ein Fehler auftritt. Gerade wenn mehrere Berechnungen, Abfragen oder Objektzugriffe nacheinander ausgeführt werden, kann die eigentliche Ursache schnell untergehen.

Eine einfache Möglichkeit besteht darin, an verschiedenen Stellen im Code temporäre Debug-Ausgaben einzubauen.

Nehmen wir an, unsere Function Node erwartet folgende Struktur:

{
  "sensor": {
    "temperatur": 23
  }
}

Der Inject-Node liefert aber weiterhin nur:

{
  "temperatur": "23"
}
Injection Node mit Temperaturwert als String
Injection Node mit Temperaturwert als String

Unsere Function Node versucht trotzdem auf sensor.temperatur zuzugreifen:

const temperatur = msg.payload["sensor"]["temperatur"];

msg.status = temperatur === 23
    ? "Temperatur ist 23 °C"
    : "Temperatur ist nicht 23 °C";

return msg;

Da msg.payload["sensor"] nicht existiert, bricht der Code an dieser Stelle ab.

Fehlermeldung
{"__enc__":true,"type":"error","data":{"name":"TypeError","message":"Cannot read properties of undefined (reading 'temperatur')","stack":"TypeError: Cannot read properties of undefined (reading 'temperatur')\n    at Function node:function_error [Temperatur auswerten]:2:41\n    at Function node:function_error [Temperatur auswerten]:9:3\n    at Script.runInContext (node:vm:149:12)\n    at processMessage (/usr/src/node-red/node_modules/@node-red/nodes/core/function/10-function.js:430:37)\n    at FunctionNode._inputCallback (/usr/src/node-red/node_modules/@node-red/nodes/core/function/10-function.js:348:17)\n    at /usr/src/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:214:26\n    at Object.trigger (/usr/src/node-red/node_modules/@node-red/util/lib/hooks.js:166:13)\n    at Node._emitInput (/usr/src/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:206:11)\n    at Node.emit (/usr/src/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:190:25)"}}

Fehler mit mehreren Debug-Ausgaben eingrenzen

Um herauszufinden, an welcher Stelle der Fehler entsteht, können wir mehrere node.warn()-Ausgaben einbauen:

node.warn("Schritt 1");

const sensor = msg.payload["sensor"];

node.warn("Schritt 2");

const temperatur = sensor["temperatur"];

node.warn("Schritt 3");

return msg;

In der Debug-Seitenleiste erscheinen nun nur:

Schritt 1
Schritt 2

Die Ausgabe Schritt 3 wird nicht mehr erreicht.

Damit wissen wir, dass der Fehler zwischen der zweiten und dritten Debug-Ausgabe auftritt.

Schritt-für-Schritt Ausgabe in der Function Node
Schritt-für-Schritt Ausgabe in der Function Node

Diese Methode ist sicherlich nicht besonders elegant, kann aber bei längeren Function Nodes sehr schnell dabei helfen, einen Fehler auf wenige Zeilen einzugrenzen.

Den problematischen Wert direkt prüfen

Anstatt nur mit Schrittmarken zu arbeiten, können wir uns zusätzlich den Inhalt der verdächtigen Variable anzeigen lassen:

const sensor = msg.payload["sensor"];

node.warn({
    sensor: sensor,
    typ: typeof sensor
});

Die Ausgabe zeigt:

sensor: undefined
typ: "undefined"

Damit ist die Ursache eindeutig.

Object sensor undefined im JavaScript Code
Object sensor undefined im JavaScript Code

Nicht der Zugriff auf temperatur ist das eigentliche Problem, sondern bereits sensor ist nicht vorhanden.

Bevor wir also auf sensor["temperatur"] zugreifen, sollten wir prüfen, ob sensor überhaupt existiert.

Zum Beispiel:

const sensor = msg.payload["sensor"];

if (sensor === undefined) {
    node.warn("Sensor-Daten fehlen");
    return null;
}

const temperatur = sensor["temperatur"];

return msg;

Auf diese Weise verhindern wir, dass der JavaScript-Code an dieser Stelle einfach abbricht.

Warnung wenn das sensor Object undefined ist
Warnung wenn das sensor Object undefined ist

Bis hierhin konnten wir den Fehler direkt innerhalb des Flows beziehungsweise der Function Node eingrenzen. Nicht jedes Problem lässt sich jedoch auf diese Weise erkennen. Manche Fehler treten erst während des laufenden Betriebs auf oder werden von Node-RED selbst beziehungsweise von installierten Nodes erzeugt. In solchen Fällen lohnt sich ein Blick in die Laufzeit-Logs.

Node-RED-Logs prüfen

Nicht jeder Fehler lässt sich direkt im Flow oder in der Debug-Seitenleiste erkennen. Manche Probleme tauchen erst im laufenden Betrieb auf – zum Beispiel wenn ein Node eine Exception wirft, Node-RED neu startet oder der Prozess mit einer Speicherfehlermeldung beendet wird.

Je nachdem, wie Node-RED installiert wurde, unterscheiden sich die Befehle für den Zugriff auf die Logs.

Variante 1: Node-RED direkt im Terminal gestartet

Wenn du Node-RED direkt mit dem Befehl node-red startest, läuft der Prozess im aktuellen Terminalfenster. In diesem Fall werden viele Laufzeitmeldungen direkt dort ausgegeben.

Das ist die einfachste Variante, weil du keine zusätzlichen Werkzeuge wie journalctl oder docker logs benötigst.

Nach dem Start siehst du zunächst typische Informationen wie die verwendete Node-RED-Version, den Speicherort der settings.js und den gestarteten Webserver.

Während Node-RED läuft, erscheinen dort außerdem Warnungen und Fehlermeldungen, die vom laufenden Prozess ausgegeben werden.

Node-RED lokal starten
Node-RED lokal starten

Wenn du beispielsweise innerhalb einer Function Node folgendes verwendest:

node.warn("Sensor-Daten fehlen");

kann diese Meldung zusätzlich zur Debug-Seitenleiste auch in der Terminalausgabe erscheinen.

Ausgabe Sensor-Daten fehlen im Debug-Tab von Node-RED
Ausgabe Sensor-Daten fehlen im Debug-Tab von Node-RED
Ausgabe einer Warnung im Log von Node-RED
Ausgabe einer Warnung im Log von Node-RED

Das ist besonders praktisch, wenn du einen Fehler gerade reproduzierst. Du kannst den Flow im Browser ausführen und gleichzeitig das Terminal beobachten.

Ein typischer Ablauf sieht dann so aus:

Node-RED Debugging-Workflow in vier Schritten
Node-RED Debugging-Workflow in vier Schritten

Wichtig ist dabei: Sobald du das Terminal beziehungsweise den laufenden Prozess beendest, wird auch Node-RED beendet.

Diese Variante eignet sich deshalb vor allem für lokale Entwicklungsumgebungen, Tests oder zum gezielten Debuggen. Für einen dauerhaften Betrieb wird Node-RED häufig als Service oder innerhalb eines Docker-Containers gestartet.

Variante 2: Node-RED als systemd-Service

Wenn Node-RED als Dienst läuft, kannst du die letzten Meldungen mit journalctl anzeigen:

journalctl -u nodered --no-pager -n 100

Für einen bestimmten Zeitraum:

journalctl -u nodered --since "1 hour ago"
Logausgabe mit journalctl beim Service Node-RED
Logausgabe mit journalctl beim Service Node-RED

Oder live:

journalctl -u nodered -f
Logausgabe im Live-Modus - Service Node-RED
Logausgabe im Live-Modus – Service Node-RED

Damit lassen sich Fehler direkt beobachten, während du einen Flow testest.

Variante 3: Node-RED im Docker-Container

Läuft Node-RED in Docker, verwendest du stattdessen die Container-Logs.

Zuerst kannst du dir die laufenden Container anzeigen lassen:

docker ps
Ausgabe der laufenden Docker Container
Ausgabe der laufenden Docker Container

Anschließend liest du die Logs des Node-RED-Containers aus:

docker logs <container-name>

Zum Beispiel:

docker logs nodered
Logausgabe von Node-RED im Docker Container
Logausgabe von Node-RED im Docker Container

Nur die letzten 100 Zeilen:

docker logs --tail 100 nodered

Oder live:

docker logs -f nodered

Praktisch ist auch:

docker logs --tail 100 -f nodered

Damit siehst du zunächst die letzten Meldungen und anschließend alle neuen Einträge in Echtzeit.

Ausgabe der letzten Nachrichten inkl der aktuellen
Ausgabe der letzten Nachrichten inkl der aktuellen

Gezielt nach Fehlern suchen

Unabhängig vom Setup sind unter anderem folgende Begriffe interessant:

  • Error
  • Exception
  • TypeError
  • ReferenceError
  • MaxListeners
  • heap out of memory

Bei einem systemd-Service kannst du beispielsweise filtern mit:

journalctl -u nodered --no-pager | grep -iE "warn|error|exception|TypeError|ReferenceError"
Ausgeben von definierten Logeinträgen
Ausgeben von definierten Logeinträgen

Bei Docker:

docker logs nodered 2>&1 | grep -iE "error|exception|TypeError|ReferenceError"
ausgabe definierte Logeinträge aus einem Docker Container
ausgabe definierte Logeinträge aus einem Docker Container

Für Speicherprobleme:

journalctl -u nodered --no-pager | grep -iE "heap out of memory|MaxListeners"

beziehungsweise:

docker logs nodered 2>&1 | grep -iE "heap out of memory|MaxListeners"

Node-RED-Logs für einen neuen Test sichern und übersichtlich halten

Beim Debuggen ist es oft hilfreich, mit einer möglichst übersichtlichen Logausgabe zu arbeiten. Je nach Installation von Node-RED unterscheidet sich der Weg etwas.

Variante 1: Node-RED als systemd-Service

Wenn Node-RED als systemd-Service läuft, werden die Meldungen im systemd-Journal gespeichert. Eine einzelne Logdatei nur für Node-RED gibt es dabei normalerweise nicht.

Bevor du mit einem neuen Test beginnst, kannst du die bisherigen Node-RED-Logs zunächst sichern:

journalctl -u nodered --no-pager > "nodered-$(date +%Y%m%d-%H%M%S).log"

Damit erhältst du eine Textdatei mit allen bisherigen Meldungen des Services.

Ein gezieltes Leeren nur für den Node-RED-Service ist bei journalctl nicht vorgesehen. Für das Debugging ist es deshalb meist sinnvoller, anschließend nur neue Meldungen live zu beobachten:

journalctl -u nodered -f

Oder du filterst die Ausgabe nach einem bestimmten Zeitraum:

journalctl -u nodered --since "5 minutes ago"

Wenn du das gesamte Journal tatsächlich aufräumen möchtest, kannst du es rotieren und alte Einträge entfernen:

sudo journalctl --rotate
sudo journalctl --vacuum-time=1s

Wichtig: Dabei werden nicht nur Node-RED-Logs, sondern auch andere ältere systemd-Journaleinträge entfernt.

Variante 2: Node-RED im Docker-Container

Läuft Node-RED in einem Docker-Container, kannst du zunächst den Pfad der aktuellen Container-Logdatei ermitteln:

docker inspect -f '{{.LogPath}}' nodered

Bevor du die Datei leerst, solltest du sie sichern:

sudo cp "$(docker inspect -f '{{.LogPath}}' nodered)" \
        "$(docker inspect -f '{{.LogPath}}' nodered).backup"

Anschließend kannst du die aktuelle Logdatei leeren:

sudo truncate -s 0 "$(docker inspect -f '{{.LogPath}}' nodered)"

Danach zeigt

docker logs nodered

nur noch die neu erzeugten Meldungen an.

Das ist beim Debuggen sehr praktisch, weil alte Logeinträge nicht mehr zwischen den aktuellen Warnungen und Fehlern stehen.

Wichtig: Dieser Weg funktioniert nur bei einem dateibasierten Docker-Logging-Treiber wie json-file. Für den dauerhaften Betrieb ist eine Log-Rotation sinnvoller als das regelmäßige manuelle Leeren.

Speicherprobleme in Node-RED erkennen

Nicht jedes Problem in Node-RED tritt sofort als JavaScript-Fehler oder Warnung im Log auf. Gerade Speicherprobleme machen sich oft erst nach längerer Laufzeit bemerkbar.

Ein typisches Beispiel ist ein Prozess, dessen Speicherverbrauch über Stunden immer weiter ansteigt. Anfangs funktioniert der Flow noch problemlos, später reagiert Node-RED langsamer oder der Prozess wird im schlimmsten Fall wegen Speichermangels beendet.

Mögliche Hinweise auf ein Speicherproblem sind beispielsweise:

  • der RAM-Verbrauch steigt dauerhaft an,
  • Node-RED wird nach längerer Laufzeit langsamer,
  • der Prozess startet unerwartet neu,
  • im Log erscheint JavaScript heap out of memory,
  • oder es treten Warnungen wie MaxListenersExceededWarning auf.

Wichtig dabei: Eine einzelne Warnung bedeutet noch nicht automatisch, dass ein Memory Leak vorliegt. Entscheidend ist vielmehr, ob sich über einen längeren Zeitraum ein auffälliger Trend erkennen lässt.

Bevor wir einen Heap Snapshot erstellen, sollten wir deshalb zunächst beobachten, wie sich der Speicherverbrauch des laufenden Node-RED-Prozesses entwickelt.

Speicherverbrauch beobachten

Wenn der Verdacht besteht, dass Node-RED über längere Zeit immer mehr Arbeitsspeicher benötigt, sollten wir zunächst beobachten, wie sich der Speicherverbrauch entwickelt.

Ein einzelner Messwert reicht dafür nicht aus. Interessant ist vielmehr der Verlauf über mehrere Stunden.

Für diesen Zweck können wir direkt innerhalb von Node-RED einen kleinen Heap-Monitor verwenden.

Der Flow besteht aus zwei Nodes:

Node-RED Flow zum loggen des Speicherverbrauchs
Node-RED Flow zum loggen des Speicherverbrauchs
Node-RED Flow zum analysieren des Speichers
[
    {
        "id": "4ab7232c03630de1",
        "type": "tab",
        "label": "Heap Monitor",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "hm_inject",
        "type": "inject",
        "z": "4ab7232c03630de1",
        "name": "alle 5 min",
        "props": [],
        "repeat": "300",
        "crontab": "",
        "once": true,
        "onceDelay": "10",
        "topic": "",
        "x": 110,
        "y": 80,
        "wires": [
            [
                "hm_func"
            ]
        ]
    },
    {
        "id": "hm_func",
        "type": "function",
        "z": "4ab7232c03630de1",
        "name": "Heap Monitor",
        "func": "const h = v8.getHeapStatistics();\nconst old = v8.getHeapSpaceStatistics().find(s => s.space_name === 'old_space');\nconst used = Math.round(h.used_heap_size / 1048576);\nconst oldUsed = Math.round(old.space_used_size / 1048576);\n\n// Stundenminimum (kurz nach einer GC, daher kaum Müll enthalten)\nlet st = context.get('st') || { min: Infinity, start: Date.now() };\nst.min = Math.min(st.min, used);\nif (Date.now() - st.start >= 3600000) {\n    node.warn('STUNDENMINIMUM heap=' + st.min + 'MB');\n    st = { min: Infinity, start: Date.now() };\n}\ncontext.set('st', st);\n\n// erster Durchlauf sofort, danach jeder 5.\nconst n = (context.get('n') || 0) + 1;\ncontext.set('n', n);\nif (n % 5 === 1) {\n    node.warn('heap=' + used + 'MB old=' + oldUsed + 'MB');\n}\n\nnode.status({ text: used + ' MB / old ' + oldUsed + ' MB' });\nreturn null;",
        "outputs": 0,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "v8",
                "module": "v8"
            }
        ],
        "x": 300,
        "y": 80,
        "wires": []
    }
]

Der Inject-Node wird alle fünf Minuten ausgelöst und startet die Messung automatisch zehn Sekunden nach dem Deploy.

Die Function Node liest anschließend die Speicherinformationen der V8-JavaScript-Engine aus.

Logausgabe des Heap Monitor Flows in Node-RED
Logausgabe des Heap Monitor Flows in Node-RED

Speicherinformationen mit dem V8-Modul auslesen

In der Function Node wird das Node.js-Modul v8 eingebunden.

Dazu wird innerhalb der Function Node unter Setup → Modules folgendes Modul hinzugefügt:

Function Node - Modul v8 eingebunden
Function Node – Modul v8 eingebunden

Anschließend können wir die Heap-Statistiken auslesen:

const h = v8.getHeapStatistics();

const old = v8.getHeapSpaceStatistics()
    .find(s => s.space_name === "old_space");

const used = Math.round(
    h.used_heap_size / 1048576
);

const oldUsed = Math.round(
    old.space_used_size / 1048576
);

used_heap_size zeigt uns, wie viel Speicher aktuell innerhalb des JavaScript-Heaps verwendet wird.

Zusätzlich betrachten wir den sogenannten old_space.

Dort landen Objekte, die mehrere Garbage-Collection-Durchläufe überlebt haben und deshalb länger im Speicher verbleiben.

Gerade bei der Suche nach einem möglichen Memory Leak ist dieser Wert interessant.

Werte regelmäßig protokollieren

Unser Flow schreibt nicht bei jedem Durchlauf eine Meldung in das Log.

Stattdessen wird nur bei jedem fünften Durchlauf eine Ausgabe erzeugt:

const n = (context.get("n") || 0) + 1;

context.set("n", n);

if (n % 5 === 1) {
    node.warn(
        "heap=" + used + "MB old=" + oldUsed + "MB"
    );
}

Da der Inject-Node alle fünf Minuten ausgelöst wird, erhalten wir damit ungefähr alle 25 Minuten einen Logeintrag.

Zum Beispiel: heap=84MB old=51MB

Die Werte werden zusätzlich direkt unterhalb der Function Node angezeigt:

node.status({
    text: used + " MB / old " + oldUsed + " MB"
});

Damit lässt sich der aktuelle Zustand auch direkt im Flow erkennen.

Das Stundenminimum beobachten

Der aktuelle Heap-Verbrauch schwankt ständig.

Das liegt unter anderem daran, dass Node.js regelmäßig nicht mehr benötigte Objekte über die Garbage Collection aus dem Speicher entfernt.

Deshalb ist ein einzelner hoher Wert nicht automatisch problematisch.

Interessanter ist der niedrigste Speicherwert innerhalb eines längeren Zeitraums.

Unser Flow speichert deshalb innerhalb einer Stunde den kleinsten gemessenen Heap-Wert:

let st = context.get("st") || {
    min: Infinity,
    start: Date.now()
};

st.min = Math.min(st.min, used);

Nach einer Stunde wird dieser Wert ausgegeben:

if (Date.now() - st.start >= 3600000) {

    node.warn(
        "STUNDENMINIMUM heap=" + st.min + "MB"
    );

    st = {
        min: Infinity,
        start: Date.now()
    };
}

Dadurch erhalten wir beispielsweise: STUNDENMINIMUM heap=72MB und eine Stunde später: STUNDENMINIMUM heap=79MB
später vielleicht: STUNDENMINIMUM heap=88MB

Steigt dieses Minimum über viele Stunden kontinuierlich an, obwohl sich die Last des Systems nicht wesentlich verändert, kann das ein Hinweis darauf sein, dass Objekte dauerhaft im Speicher verbleiben.

Ein steigender Heap ist nicht automatisch ein Memory Leak

Wichtig ist, die Werte nicht isoliert zu betrachten.

Node.js reserviert Speicher dynamisch und gibt ihn nicht zwingend sofort wieder an das Betriebssystem zurück. Auch der Heap selbst kann deshalb zeitweise wachsen, ohne dass tatsächlich ein Fehler vorliegt.

Interessant wird es vor allem dann, wenn sich ein Muster zeigt:

Stunde 1: 72 MB
Stunde 2: 79 MB
Stunde 3: 88 MB
Stunde 4: 96 MB
Stunde 5: 107 MB

Sinkt der Heap auch nach mehreren Garbage-Collection-Durchläufen nicht mehr auf frühere Werte zurück, lohnt sich eine genauere Untersuchung.

Genau dafür können wir im nächsten Schritt einen Heap Snapshot erzeugen und prüfen, welche Objekte tatsächlich im Speicher verbleiben.

Fazit

Fehler in Node-RED lassen sich meistens deutlich schneller finden, wenn man systematisch vorgeht und nicht sofort an der kompliziertesten Stelle sucht.

Der erste Blick sollte deshalb immer auf die Nachricht selbst gehen: Kommen die erwarteten Werte an, stimmt die Struktur von msg und besitzen die Werte den richtigen Datentyp? Mit dem Debug-Node, node.warn() und kleinen Ausgaben innerhalb einer Function Node lassen sich viele JavaScript-Probleme bereits sehr schnell eingrenzen.

Reicht das nicht aus, lohnt sich der Blick auf die Laufzeit-Logs von Node-RED. Je nachdem, wie Node-RED gestartet wurde, findest du diese direkt im Terminal, über journalctl oder mit docker logs. Gerade Fehler, Warnungen oder unerwartete Neustarts werden hier oft deutlicher sichtbar als innerhalb des Editors.

Etwas schwieriger wird es bei Problemen, die erst nach mehreren Stunden oder Tagen auftreten. Ein stetig steigender Speicherverbrauch kann ein Hinweis darauf sein, dass Objekte länger im Speicher verbleiben als erwartet. Mit dem gezeigten Heap-Monitor lässt sich zunächst beobachten, ob sich tatsächlich ein auffälliger Trend entwickelt.

Wichtig ist dabei: Ein hoher Speicherwert allein bedeutet noch kein Memory Leak. Entscheidend ist die Entwicklung über einen längeren Zeitraum.

Wenn sich der Verdacht bestätigt, reicht das reine Beobachten allerdings nicht mehr aus. Dann müssen wir tiefer in den Node.js-Prozess schauen und beispielsweise mit Heap Snapshots untersuchen, welche Objekte im Speicher verbleiben.

Transparenzhinweis: Dieser Beitrag wurde mit Unterstützung künstlicher Intelligenz erstellt und redaktionell geprüft. Mehr zur Nutzung von KI

Letzte Aktualisierung am: 24. Oktober 2026

Foto von Stefan Draeger
Über den Autor

Stefan Draeger — Entwickler & Tech-Blogger

Ich zeige praxisnah, wie du Projekte mit Arduino, ESP32 und Smarthome-Komponenten umsetzt – Schritt für Schritt, mit Code und Schaltplänen.

Mehr Artikel von Stefan →

Schreibe einen Kommentar Antwort abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Kategorien

Kontakt & Hilfe

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden? Erstelle einfach ein Support-Ticket.

Support-Ticket erstellen
Keine Beiträge verpassen

Newsletter abonnieren

Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32, Smarthome und IoT direkt in dein Postfach.

Newsletter abonnieren
Videos & Tutorials

Draeger-IT auf YouTube

Entdecke meine Videos zu Arduino, ESP32, Raspberry Pi, Smarthome und spannenden Elektronikprojekten – mit Tutorials, Tests und Praxisbeispielen.

YouTube-Kanal besuchen
Freiwillige Unterstützung

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee. So hilfst du dabei, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

Auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kostenlose Online-Werkzeuge

Tools

Praktische Generatoren, Rechner und Hilfsmittel für deine Elektronik- und Entwicklungsprojekte.

Generatoren & Konverter

  • QR-Code Generator
  • Passwort Generator
  • PNG zu WebP konvertieren
  • Bilder online komprimieren
  • Code online formatieren

Rechner & Tabellen

  • Unix-Zeitstempel-Rechner
  • ASCII-Tabelle
  • ASCII Code umrechnen – Text, Dezimal, Hex & Binär
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner

LED-Matrix

  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix Generator
Kontakt

Anschrift & Kontaktdaten

Stefan Draeger

Königsberger Str. 13
38364 Schöningen

Telefon 01556 5432686

E-Mail info@draeger-it.blog

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com
Social Media

Folge mir auf

Weitere Projekte, Videos und Neuigkeiten findest du auch auf meinen Social-Media-Kanälen.

  • f Facebook
  • in LinkedIn
  • ▶ YouTube
  • ♪ TikTok
  • P Pinterest
  • ◎ Instagram
Rechtliche Informationen

Rechtliches

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
  • KI-Transparenz bei draeger-it.blog
©2026 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
  • Optionen verwalten
  • Dienste verwalten
  • Verwalten von {vendor_count}-Lieferanten
  • Lese mehr über diese Zwecke
Einstellungen anzeigen
  • {title}
  • {title}
  • {title}