Signatur
Beschreibung
Die Eigenschaft stack einer Error-Instanz enthält eine textuelle Rückverfolgung des Aufrufstapels (Stacktrace) zu dem Zeitpunkt, an dem das Fehlerobjekt erzeugt wurde – nicht dem Zeitpunkt, an dem es geworfen wird. Jede Zeile beschreibt einen Stack-Frame, meist mit Funktionsname, Datei-URL, Zeilen- und Spaltennummer. Aktuelle Engines geben die Argumentwerte der Funktionen nicht mehr aus.
Gebraucht wird stack vor allem zum Debuggen und Protokollieren: in Log-Dateien, bei Fehler-Monitoring-Diensten (z. B. Sentry) oder in globalen Fehlerbehandlern wie window.onerror und process.on("uncaughtException"). So lässt sich auch bei Fehlern im Produktivbetrieb nachvollziehen, woher sie stammen.
Die Eigenschaft ist nicht Teil des ECMAScript-Standards (ein Vorschlag „Error Stacks“ ist in Arbeit). Deshalb unterscheidet sich das Format zwischen den Engines: V8 (Chrome, Edge, Node.js, Deno) beginnt mit Name: Nachricht und listet danach Zeilen der Form at fn (datei:zeile:spalte). SpiderMonkey (Firefox) und JavaScriptCore (Safari) nutzen dagegen fn@datei:zeile:spalte und lassen die Kopfzeile weg. In V8 ist stack eine eigene Eigenschaft der Instanz, in Firefox ein Accessor auf Error.prototype.
Die Eigenschaft ist beschreibbar. Das ist praktisch, um Stacktraces anzupassen oder zu kürzen. Wer Stacktraces maschinell auswerten will, sollte sich aber nie auf ein festes Format verlassen.
Rückgabewert
undefined sein.Beispiele
Stacktrace eines abgefangenen Fehlers ausgeben
const ladeBenutzer = (id) => {
if (typeof id !== "number") {
throw new TypeError(`Ungültige ID: ${id}`);
}
return { id };
};
const init = () => ladeBenutzer("abc");
try {
init();
} catch (err) {
console.log(err.stack);
}
Eigene Fehlerklasse mit sauberem Stacktrace
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
// Konstruktor-Frame aus dem Stack entfernen (V8, neuere Firefox/Safari)
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, ValidationError);
}
}
}
const pruefeEmail = (email) => {
if (!email.includes("@")) {
throw new ValidationError("E-Mail ungültig", "email");
}
};
try {
pruefeEmail("max.example.com");
} catch (err) {
console.log(err.stack.split("\n")[0]);
}
Fehler für das Logging aufbereiten
const serialisiereFehler = (err) => ({
name: err?.name ?? "UnknownError",
message: err?.message ?? String(err),
// stack kann fehlen – etwa wenn ein String geworfen wurde
stack: err instanceof Error ? err.stack : undefined,
zeit: new Date().toISOString(),
});
const sendeLog = async (eintrag) => {
await fetch("/api/logs", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(eintrag),
});
};
window.addEventListener("error", (event) => {
sendeLog(serialisiereFehler(event.error));
});
window.addEventListener("unhandledrejection", (event) => {
sendeLog(serialisiereFehler(event.reason));
});
Stacktrace-Tiefe in Node.js erhöhen
// Standard in V8: 10 Frames
Error.stackTraceLimit = 50;
const rekursiv = (n) => {
if (n === 0) throw new Error("Tief unten");
rekursiv(n - 1);
};
try {
rekursiv(30);
} catch (err) {
const frames = err.stack.split("\n").filter((z) => z.trim().startsWith("at "));
console.log(`Anzahl Frames: ${frames.length}`);
}
// Wichtig · Fallstricke
- Nicht standardisiert: Format, Kopfzeile und Anzahl der Frames hängen von der Engine ab. Wer Stacktraces zuverlässig parsen will, sollte eine Bibliothek wie
stacktrace-parserodererror-stack-parserverwenden, statt eigene reguläre Ausdrücke zu schreiben. - Erzeugung statt Wurf: Der Stack wird festgehalten, wenn
new Error()aufgerufen wird. Wer ein Fehlerobjekt vorab erzeugt und erst später wirft, bekommt den Stack der Erzeugung. - Nur bei echten Fehlern: Mit
throw "Text"oderthrow {}geworfene Werte haben keinenstack. Deshalb immer Instanzen vonErrorwerfen. - Kopfzeile in V8: Die Zeile
Name: Nachrichtwird beim ersten Zugriff aufstackgebildet. Wernameodermessageerst danach ändert, sieht die Änderung nicht im Stack. - Asynchroner Code: Über
awaithinweg zeigen V8 (async stack traces) und die DevTools die Frames zum Teil an, beisetTimeout- oder Callback-Ketten fehlen sie meist. MitError.prototype.cause(ES2022) lassen sich Fehlerketten erhalten. - Gebündelter oder minifizierter Code: Zeilen- und Spaltenangaben beziehen sich auf den ausgelieferten Code. Um sie auf die Originalquellen zurückzuführen, braucht man Source Maps (in Node.js z. B. über
--enable-source-maps). - Sicherheit: Stacktraces verraten Dateipfade, interne Modulnamen und den Aufbau der Anwendung. Zeige sie deshalb nie Endnutzern an und gib sie in HTTP-Antworten von Servern nicht nach außen. Protokolliere sie nur intern.
- Performance: Einen Stacktrace zu erfassen kostet Zeit. Ein höheres
Error.stackTraceLimit(nur V8) macht jede Fehlererzeugung teurer.