Signatur
Beschreibung
Ein SuppressedError entsteht, wenn während der Behandlung eines Fehlers ein zweiter Fehler auftritt. Typisch ist das beim Aufräumen von Ressourcen mit using, await using, DisposableStack oder AsyncDisposableStack: Wenn der Block einen Fehler wirft und danach auch [Symbol.dispose]() fehlschlägt, bündelt JavaScript beide Fehler in einem SuppressedError. So geht keiner der beiden verloren.
Die Eigenschaft error enthält den neueren Fehler, also den, der die Unterdrückung ausgelöst hat (zum Beispiel den Fehler beim Aufräumen). Der ältere, verdrängte Fehler steht in suppressed. Wer den eigentlichen Grund für das Scheitern sucht, findet ihn deshalb oft in suppressed. Der Fehler beim Aufräumen steht dagegen in error.
error ist eine eigene Dateneigenschaft der Instanz und liegt nicht auf dem Prototyp. Sie ist beschreibbar (writable) und konfigurierbar (configurable), aber nicht aufzählbar (enumerable: false). Ihr Wert ist das erste Argument, das an den Konstruktor new SuppressedError(error, suppressed, message) übergeben wurde. Er kann einen beliebigen Typ haben, denn in JavaScript lässt sich jeder Wert werfen.
Rückgabewert
error übergeben wurde. Meist ist das eine Error-Instanz, es kann aber jeder beliebige geworfene Wert sein, auch undefined.Beispiele
Direkte Instanziierung und Zugriff
const aufraeumFehler = new Error('Datei konnte nicht geschlossen werden');
const ursprung = new TypeError('Ungültige Eingabe');
const err = new SuppressedError(aufraeumFehler, ursprung, 'Fehler beim Aufräumen');
console.log(err.error.message); // neuerer Fehler
console.log(err.suppressed.message); // verdrängter Fehler
console.log(Object.keys(err)); // nicht aufzählbar
Fehler in using-Block und in Symbol.dispose
const oeffneVerbindung = (name) => ({
name,
[Symbol.dispose]() {
throw new Error(`Schließen von ${name} fehlgeschlagen`);
}
});
try {
using conn = oeffneVerbindung('db');
throw new Error('Abfrage fehlgeschlagen');
} catch (e) {
if (e instanceof SuppressedError) {
console.log('Aufräumen:', e.error.message);
console.log('Ursache:', e.suppressed.message);
}
}
Verschachtelte SuppressedErrors mit DisposableStack auflösen
const stack = new DisposableStack();
stack.defer(() => { throw new Error('Cleanup A'); });
stack.defer(() => { throw new Error('Cleanup B'); });
// Alle Fehler einer Kette einsammeln
const sammleFehler = (e) =>
e instanceof SuppressedError
? [e.error, ...sammleFehler(e.suppressed)]
: [e];
try {
stack.dispose(); // LIFO: erst B, dann A
} catch (e) {
console.log(sammleFehler(e).map((f) => f.message));
}
// Wichtig · Fallstricke
- Reihenfolge nicht verwechseln:
errorist der neuere Fehler, der unterdrückt hat, undsuppressedder ältere, verdrängte. Die eigentliche Ursache aus dem Block steht deshalb häufig insuppressed. - Verschachtelung: Schlagen mehrere Aufräumschritte fehl, entstehen verschachtelte
SuppressedError-Objekte. Dann kannsuppressedselbst wieder einSuppressedErrorsein. Um alle Fehler zu erfassen, muss man die Kette rekursiv durchlaufen. - Beliebiger Typ:
errormuss keineError-Instanz sein. Prüfe den Typ, bevor du auf.messageoder.stackzugreifst. - Nicht aufzählbar:
JSON.stringify(err)undObject.keys(err)enthaltenerrornicht. Für Logging solltest du die Eigenschaft ausdrücklich auslesen. - Kompatibilität:
SuppressedErrorgehört zu Explicit Resource Management und ist noch recht neu. In Safari und älteren Laufzeitumgebungen fehlt es. Vorher mittypeof SuppressedError !== 'undefined'prüfen oder ein Polyfill wiecore-jsverwenden. TypeScript unterstützt es ab Version 5.2 mitlib: ["esnext.disposable"].