Start · Sprachen · JavaScript · Referenz · SuppressedError

SuppressedError

Klasse

Repräsentiert einen Fehler, der während der Behandlung eines anderen Fehlers auftritt – eingeführt durch das <code>using</code>-Schlüsselwort (Explicit Resource Management).

seit JavaScript ES2022 (Explicit Resource Management) Kategorie: core

Signatur

class SuppressedError extends Error

Beschreibung

SuppressedError ist ein spezieller Fehlertyp, der entsteht, wenn beim Aufräumen einer Ressource (z. B. im Dispose-Handler eines using-Blocks) ein neuer Fehler geworfen wird, während bereits ein anderer Fehler aktiv ist. In diesem Fall würde der ursprüngliche Fehler „unterdrückt" werden – SuppressedError kombiniert beide Fehler, sodass keine Information verloren geht.

Das Objekt erweitert die eingebaute Error-Klasse und fügt zwei zusätzliche Eigenschaften hinzu: error enthält den neu geworfenen (äußeren) Fehler, der den ursprünglichen verdeckt hat, und suppressed enthält den ursprünglich unterdrückten Fehler. So bleibt die vollständige Fehlerkette nachvollziehbar.

SuppressedError wird primär von der JavaScript-Engine selbst erzeugt, wenn das using- oder await using-Schlüsselwort aus dem Explicit Resource Management-Proposal (TC39 Stage 4, ES2022+) verwendet wird. Es kann aber auch manuell instanziiert werden, um eigene Ressourcenverwaltungs-Abstraktionen zu implementieren.

Da SuppressedError von Error erbt, funktionieren alle üblichen Fehlerbehandlungs-Mechanismen (instanceof, try/catch, message, stack) wie gewohnt. Die Klasse ist eng mit Symbol.dispose und Symbol.asyncDispose verwandt.

Parameter

Name Typ Default Beschreibung
$error Pflicht any Der Fehler, der den ursprünglichen Fehler verdeckt hat – also der neue, während der Bereinigung geworfene Fehler.
$suppressed Pflicht any Der ursprüngliche Fehler, der durch den neuen Fehler unterdrückt wurde.
$message string "" Eine optionale, menschenlesbare Fehlermeldung, die über error.message abrufbar ist.

Rückgabewert

Typ
SuppressedError
Beschreibung
Eine neue Instanz von SuppressedError mit den Eigenschaften error, suppressed und message.

Beispiele

Manuelles Erzeugen eines SuppressedError

const originalError = new Error("Datenbankverbindung verloren");
const cleanupError = new Error("Ressource konnte nicht freigegeben werden");

const suppressed = new SuppressedError(
  cleanupError,   // error   – der neue, verdeckende Fehler
  originalError,  // suppressed – der ursprüngliche Fehler
  "Beim Aufräumen trat ein weiterer Fehler auf"
);

console.log(suppressed instanceof SuppressedError); // true
console.log(suppressed instanceof Error);           // true
console.log(suppressed.message);    // "Beim Aufräumen trat ein weiterer Fehler auf"
console.log(suppressed.error.message);     // "Ressource konnte nicht freigegeben werden"
console.log(suppressed.suppressed.message); // "Datenbankverbindung verloren"
true true Beim Aufräumen trat ein weiterer Fehler auf Ressource konnte nicht freigegeben werden Datenbankverbindung verloren

Automatische Erzeugung durch using und Symbol.dispose

// Explicit Resource Management (ES2022+, requires transpiler or native support)
const makeResource = (name, shouldThrow = false) => ({
  [Symbol.dispose]() {
    console.log(`Dispose: ${name}`);
    if (shouldThrow) throw new Error(`Dispose-Fehler in ${name}`);
  }
});

try {
  using res1 = makeResource("Ressource A", true); // wirft beim Dispose
  throw new Error("Primärer Fehler im Block");      // wird unterdrückt
} catch (err) {
  if (err instanceof SuppressedError) {
    console.log("SuppressedError gefangen!");
    console.log("Neuer Fehler:        ", err.error.message);
    console.log("Unterdrückter Fehler:", err.suppressed.message);
  } else {
    console.log("Anderer Fehler:", err.message);
  }
}
Dispose: Ressource A SuppressedError gefangen! Neuer Fehler: Dispose-Fehler in Ressource A Unterdrückter Fehler: Primärer Fehler im Block

Fehlerkette vollständig traversieren

const traverseSuppressed = (err, depth = 0) => {
  const indent = "  ".repeat(depth);
  console.log(`${indent}[${err.constructor.name}] ${err.message}`);
  if (err instanceof SuppressedError) {
    console.log(`${indent}→ error (verdeckend):`);
    traverseSuppressed(err.error, depth + 1);
    console.log(`${indent}→ suppressed (unterdrückt):`);
    traverseSuppressed(err.suppressed, depth + 1);
  }
};

const chain = new SuppressedError(
  new SuppressedError(
    new Error("Tiefster Dispose-Fehler"),
    new Error("Mittlerer Fehler"),
    "Zweiter SuppressedError"
  ),
  new Error("Ursprünglicher Block-Fehler"),
  "Erster SuppressedError"
);

traverseSuppressed(chain);
[SuppressedError] Erster SuppressedError → error (verdeckend): [SuppressedError] Zweiter SuppressedError → error (verdeckend): [Error] Tiefster Dispose-Fehler → suppressed (unterdrückt): [Error] Mittlerer Fehler → suppressed (unterdrückt): [Error] Ursprünglicher Block-Fehler

// Wichtig · Fallstricke

Browser- und Laufzeit-Kompatibilität: SuppressedError ist Teil des Explicit Resource Management-Proposals (TC39 Stage 4). Native Unterstützung ist ab Chrome 125+, Firefox 134+, Safari 18.2+ und Node.js 22+ verfügbar. Für ältere Umgebungen werden Transpiler wie TypeScript 5.2+ oder Babel benötigt.

Verhältnis zu AggregateError: Im Gegensatz zu AggregateError, das eine Liste gleichwertiger Fehler bündelt (z. B. bei Promise.any), modelliert SuppressedError explizit ein zeitliches Kausalverhältnis: Ein Fehler tritt während der Behandlung eines anderen auf.

Kein direkter Stack-Merge: Die stack-Eigenschaft von SuppressedError selbst enthält nur den Stack des SuppressedError-Objekts. Die Stack Traces von error und suppressed sind separat über deren eigene stack-Eigenschaft zugänglich.

Achtung bei eigenen Dispose-Implementierungen: Wer Symbol.dispose oder Symbol.asyncDispose manuell implementiert, sollte darauf achten, eigene Fehler in SuppressedError zu kapseln, damit Konsumenten die vollständige Fehlerkette auswerten können.