Signatur
Beschreibung
Error.captureStackTrace() ist eine statische Methode, die den aktuellen Aufruf-Stack erfasst und als stack-Eigenschaft auf dem übergebenen Objekt ablegt. Das Zielobjekt muss dafür keine Error-Instanz sein. Jedes beliebige Objekt bekommt damit einen Stack-Trace im gleichen Format wie new Error().stack.
Wirklich nützlich wird die Methode durch den optionalen zweiten Parameter constructorOpt. Übergibt man eine Funktion, werden alle Frames oberhalb dieser Funktion aus dem Trace entfernt, der Aufruf der Funktion selbst eingeschlossen. So tauchen interne Details wie Konstruktoren eigener Fehlerklassen, Hilfsfunktionen oder Assertion-Wrapper nicht im Stack-Trace auf. Wer die Fehlermeldung liest, sieht sofort die Stelle im eigenen Code, an der das Problem entstanden ist.
Typische Einsatzfälle:
- eigene Fehlerklassen (
class ValidationError extends Error), deren Konstruktor nicht im Trace stehen soll - Assertion- und Test-Bibliotheken, deren interne Funktionen ausgeblendet werden sollen
- Stack-Traces an Objekten, die keine Fehler sind, zum Beispiel zum Debuggen von Ressourcen-Lecks („Wo wurde diese Verbindung geöffnet?“)
Die Methode stammt aus der JavaScript-Engine V8 und ist kein Bestandteil des ECMAScript-Standards. Mittlerweile unterstützen sie aber alle großen Engines.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $targetObject Pflicht | object | Das Objekt, auf dem die Eigenschaft stack angelegt wird. Es kann ein beliebiges Objekt sein, auch eines, das kein Error ist. |
|
| $constructorOpt | Function | undefined | Optionale Funktion. Alle Stack-Frames oberhalb des obersten Aufrufs dieser Funktion werden aus dem Trace entfernt, der Aufruf selbst eingeschlossen. Taucht die Funktion nicht im Stack auf, bleibt der Trace leer (nur die Kopfzeile). |
Rückgabewert
undefined zurück. Die Methode verändert das Zielobjekt direkt, indem sie die Eigenschaft stack darauf anlegt.Beispiele
Stack-Trace an einem beliebigen Objekt
const obj = { message: 'Hier wurde etwas erzeugt' };
Error.captureStackTrace(obj);
// Die erste Zeile stammt aus toString() des Objekts
console.log(obj.stack.split('\n')[0]);
Eigene Fehlerklasse ohne Konstruktor im Trace
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = 'ValidationError';
this.field = field;
// Konstruktor-Frame ausblenden, falls verfügbar
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, ValidationError);
}
}
}
const validateUser = (user) => {
if (!user.email) throw new ValidationError('email', 'E-Mail fehlt');
};
try {
validateUser({ name: 'Anna' });
} catch (err) {
console.log(err.stack.split('\n').slice(0, 2).join('\n'));
}
Assertion-Helfer, der sich selbst ausblendet
function assert(condition, message = 'Assertion fehlgeschlagen') {
if (!condition) {
const err = new Error(message);
// Frame von assert() entfernen: Trace beginnt beim Aufrufer
Error.captureStackTrace(err, assert);
throw err;
}
}
const divide = (a, b) => {
assert(b !== 0, 'Division durch 0');
return a / b;
};
try {
divide(10, 0);
} catch (e) {
console.log(e.stack.split('\n')[1].trim().startsWith('at divide'));
}
Herkunft offener Ressourcen verfolgen
const openHandles = new Set();
const openConnection = (name) => {
const handle = { name };
// Merken, wo die Verbindung geöffnet wurde
Error.captureStackTrace(handle, openConnection);
openHandles.add(handle);
return handle;
};
const closeConnection = (handle) => openHandles.delete(handle);
const db = openConnection('db');
openConnection('cache'); // wird nie geschlossen
closeConnection(db);
for (const h of openHandles) {
console.log(`Nicht geschlossen: ${h.name}`);
console.log(h.stack.split('\n')[1].trim());
}
// Wichtig · Fallstricke
- Nicht standardisiert: Die Methode stammt aus V8. Chrome, Edge und Node.js unterstützen sie schon lange, Firefox erst ab Version 121, Safari/JavaScriptCore ebenfalls. In Code, der in vielen Umgebungen laufen muss, vorher mit
typeof Error.captureStackTrace === 'function'prüfen. - Format von
stack: Der Inhalt ist nicht standardisiert. Die Formate von V8, SpiderMonkey und JavaScriptCore unterscheiden sich. Die Zeilen also nicht fest parsen, sondern nur für Diagnose und Logging verwenden. - Kopfzeile: Die erste Zeile des Traces entsteht über
targetObject.toString()bzw.name/message. Bei einfachen Objekten steht dort deshalb[object Object]. - Lazy-Formatierung in V8: V8 formatiert den Stack erst beim ersten Zugriff auf
stack. Das Ergebnis hängt vonError.prepareStackTraceab, und die Anzahl der Frames begrenztError.stackTraceLimit(Standard: 10). - constructorOpt nicht im Stack: Kommt die übergebene Funktion im aktuellen Stack nicht vor, bleiben keine Frames übrig.
- Performance: Einen Stack-Trace zu erfassen kostet Zeit. Die Methode daher nicht in heißen Schleifen für jedes Objekt aufrufen (etwa beim Leak-Tracking nur im Debug-Modus).
- Sicherheit: Stack-Traces verraten Dateipfade und interne Struktur. Sie gehören nicht ungefiltert in HTTP-Antworten an Clients.
- Bei
class … extends Errorist der Aufruf in modernen Engines oft unnötig, weil der Konstruktor ohnehin kaum stört. Er lohnt sich vor allem bei Factory-Funktionen und Helfern.