Signatur
Beschreibung
Die Eigenschaft cause gibt an, welcher ursprüngliche Fehler zu einem neuen Fehler geführt hat. Man setzt sie über das Optionsobjekt des Konstruktors: new Error(message, { cause }). So lassen sich Fehlerketten bauen. Ein Low-Level-Fehler wie ein Netzwerk- oder Parse-Fehler wird in einen aussagekräftigeren, fachlichen Fehler verpackt, ohne dass die technische Ursache samt Stacktrace verloren geht.
cause ist eine eigene Dateneigenschaft der Instanz, keine Eigenschaft von Error.prototype. Sie wird nur angelegt, wenn das Optionsobjekt tatsächlich einen Schlüssel cause hat. Die Eigenschaft ist beschreibbar und konfigurierbar, aber nicht aufzählbar. Deshalb erscheint sie weder in Object.keys() noch in JSON.stringify().
Der Wert kann beliebigen Typs sein: ein anderes Error-Objekt, ein String oder ein Objekt mit strukturierten Zusatzdaten. Üblich und empfohlen ist ein Error-Objekt. Die Option funktioniert bei allen eingebauten Fehlerklassen (TypeError, RangeError, AggregateError usw.) und bei eigenen Unterklassen, die die Optionen an super() weitergeben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options.cause | any | Wird im Konstruktor als zweites (bei AggregateError als drittes) Argument im Optionsobjekt übergeben. Der Wert landet unverändert in error.cause. |
Rückgabewert
cause angegeben, existiert die Eigenschaft nicht und der Zugriff liefert undefined.Beispiele
Low-Level-Fehler in fachlichen Fehler verpacken
const loadConfig = (json) => {
try {
return JSON.parse(json);
} catch (err) {
throw new Error('Konfiguration konnte nicht geladen werden', { cause: err });
}
};
try {
loadConfig('{ ungültig }');
} catch (err) {
console.log(err.message);
console.log(err.cause instanceof SyntaxError);
}
Fehlerkette bei fetch mit async/await
const fetchUser = async (id) => {
try {
const res = await fetch(`https://api.example.com/users/${id}`);
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
return await res.json();
} catch (err) {
throw new Error(`Benutzer ${id} nicht abrufbar`, { cause: err });
}
};
fetchUser(42).catch((err) => {
// Gesamte Ursachenkette ausgeben
let current = err;
while (current) {
console.log('→', current.message ?? current);
current = current.cause;
}
});
Strukturierte Ursache und eigene Fehlerklasse
class ValidationError extends Error {
constructor(message, options) {
super(message, options); // options mit cause weiterreichen
this.name = 'ValidationError';
}
}
const err = new ValidationError('Ungültige Eingabe', {
cause: { field: 'email', value: 'foo@' }
});
console.log(err.cause.field);
console.log(Object.keys(err));
console.log(Object.hasOwn(err, 'cause'));
Fehlende vs. explizit undefinierte Ursache
const a = new Error('ohne');
const b = new Error('mit', { cause: undefined });
console.log('cause' in a);
console.log('cause' in b);
// Wichtig · Fallstricke
- Kompatibilität: Seit ES2022. Unterstützt ab Chrome 93, Firefox 91, Safari 15 und Node.js 16.9. In älteren Umgebungen wird das Optionsobjekt stillschweigend ignoriert, und
causebleibt dannundefined. - Nicht aufzählbar:
JSON.stringify(err)enthältcausenicht,messageundstackübrigens auch nicht. Für Logging oder Serialisierung muss man die Ursachenkette selbst ablaufen. - Eigene Unterklassen: Das zweite Argument muss an
super(message, options)weitergereicht werden, sonst gehtcauseverloren. - Bei
AggregateErrorsteht das Optionsobjekt an dritter Stelle:new AggregateError(errors, message, { cause }). - Node.js und moderne Browser-DevTools zeigen die Ursachenkette in der Konsole meist automatisch an. Eigene Logger tun das oft nicht.
- Achtung bei Zyklen: Wenn sich eine Ursachenkette selbst referenziert, laufen rekursive Ausgabefunktionen endlos. Eine Tiefenbegrenzung ist sinnvoll.
- Sicherheit: Ursachen enthalten oft interne Details wie SQL, Pfade oder Tokens. Solche Details nicht ungefiltert an Clients ausliefern.