Signatur
Beschreibung
Die Eigenschaft suppressed gehört zu jeder Instanz von SuppressedError. Sie verweist auf den ursprünglichen Fehler, der „unterdrückt“ wurde. Den neuen Fehler, der diese Unterdrückung ausgelöst hat, findest du in der Schwester-Eigenschaft error. Beide zusammen sorgen dafür, dass bei mehreren gleichzeitigen Fehlern keine Information verloren geht.
Solche Fehler erzeugt die JavaScript-Engine vor allem bei der expliziten Ressourcenverwaltung, also mit using, await using, DisposableStack und AsyncDisposableStack. Ein typischer Fall: Ein Block wirft einen Fehler, und danach schlägt auch das Aufräumen über [Symbol.dispose]() fehl. Die Engine wirft dann einen SuppressedError. Darin steht der Aufräumfehler in error und der ursprüngliche Fehler aus dem Block in suppressed.
suppressed ist eine eigene Dateneigenschaft der Instanz, keine Getter-Eigenschaft des Prototyps. Sie ist beschreibbar, konfigurierbar und nicht aufzählbar. Ihr Wert kann beliebig sein, denn in JavaScript lässt sich jeder Wert werfen. Er kann auch selbst ein SuppressedError sein. So entstehen verschachtelte Ketten, wenn mehrere Aufräumschritte nacheinander fehlschlagen.
Rückgabewert
Error, es kann aber jeder Wert sein, auch ein weiterer SuppressedError. Wird ein SuppressedError von Hand erzeugt, ist es der zweite Konstruktor-Parameter.Beispiele
SuppressedError von Hand erzeugen und auslesen
const original = new Error("Datenbank-Abfrage fehlgeschlagen");
const cleanup = new Error("Verbindung ließ sich nicht schließen");
// Signatur: new SuppressedError(error, suppressed, message)
const err = new SuppressedError(cleanup, original, "Fehler beim Aufräumen");
console.log(err.message); // Nachricht des Sammelfehlers
console.log(err.error.message); // neuer Fehler
console.log(err.suppressed.message); // unterdrückter Originalfehler
console.log(Object.keys(err)); // nicht aufzählbar
Automatisch durch using bei fehlschlagendem Dispose
const openFile = (name) => ({
name,
[Symbol.dispose]() {
throw new Error(`Datei ${name} konnte nicht geschlossen werden`);
}
});
try {
using file = openFile("bericht.csv");
throw new Error("Ungültige Zeile 42");
} catch (e) {
if (e instanceof SuppressedError) {
console.log("Aufräumfehler:", e.error.message);
console.log("Ursprünglicher Fehler:", e.suppressed.message);
}
}
Verschachtelte Fehlerketten aus DisposableStack auflösen
// Liefert alle Fehler vom zuletzt aufgetretenen bis zum ersten
const flattenSuppressed = (err) => {
const errors = [];
let current = err;
while (current instanceof SuppressedError) {
errors.push(current.error);
current = current.suppressed;
}
errors.push(current);
return errors;
};
const stack = new DisposableStack();
stack.defer(() => { throw new Error("Cache leeren fehlgeschlagen"); });
stack.defer(() => { throw new Error("Socket schließen fehlgeschlagen"); });
try {
stack.dispose(); // räumt in umgekehrter Reihenfolge auf
} catch (e) {
console.log(flattenSuppressed(e).map((x) => x.message));
}
// Wichtig · Fallstricke
- Richtung nicht verwechseln:
suppressedenthält den älteren, ursprünglichen Fehler,errorden neueren. Wer nure.messageodere.errorprotokolliert, verliert oft die eigentliche Ursache. - Beliebiger Typ: Der Wert muss kein
Errorsein, denn auchthrow \"text\"oderthrow undefinedist möglich. Prüfe also vor dem Zugriff auf.messageoder.stack, ob es wirklich ein Fehlerobjekt ist. - Verschachtelung: Schlagen mehrere Aufräumschritte fehl, kann
suppressedselbst wieder einSuppressedErrorsein. Für ein vollständiges Protokoll musst du die Kette rekursiv durchlaufen. - Nicht aufzählbar:
suppressedtaucht weder inObject.keys()noch inJSON.stringify()auf. Für Logging oder Telemetrie musst du die Eigenschaft ausdrücklich serialisieren. - Kompatibilität:
SuppressedErrorgehört zum Vorschlag „Explicit Resource Management“, der noch sehr neu ist. Unterstützung gibt es erst in aktuellen Chromium-Versionen, in Firefox und in Node.js; Safari unterstützt ihn derzeit nicht. Prüfe vorher mittypeof SuppressedError !== \"undefined\"oder nutze ein Polyfill bzw. Transpiler wie Babel oder TypeScript 5.2+.