Error.cause (chained errors)
Allows associating a new error with an underlying original error, creating a chain of errors for better debugging context.
new Error(message, { cause: originalError })This static page keeps the syntax and examples indexed for search, while the coding app handles interactive exploration and saved references.
What it does
Overview
Allows associating a new error with an underlying original error, creating a chain of errors for better debugging context.
The `Error.cause` property, introduced in ES2022, provides a standardized and highly beneficial way to chain errors. This feature is particularly useful when you catch an error at a lower level of abstraction (e.g., a database error, a network error) and then throw a new, more specific, or higher-level error that wraps the original one. By passing an object `{ cause: originalError }` as the second argument to the `Error` constructor, you can link the new error to the exception that directly caused it. This creates a clear lineage of errors, making it much easier to trace the root cause of a problem through multiple layers of abstraction or function calls. Instead of losing the context of the initial error (which often happens when simply re-throwing a new error), `Error.cause` preserves it, significantly improving debugging efforts and error logging. It's a best practice to use `Error.cause` when re-throwing errors with additional context, as it provides a structured and discoverable way to access the full error history, unlike manually attaching arbitrary properties to error objects, which can be inconsistent.
Quick reference
Syntax
new Error(message, { cause: originalError })
Inputs
Parameters
See it in practice
Examples
Wrapping a low-level error with a high-level one
function fetchUser(userId) {
try {
// Simulate a network failure
throw new TypeError('Failed to fetch: Network unreachable');
} catch (networkErr) {
throw new Error(`Could not retrieve user ${userId}.`, { cause: networkErr });
}
}
try {
fetchUser('abc-123');
} catch (appError) {
console.error(`Application Error: ${appError.message}`);
console.error(` Caused by: ${appError.cause.name}: ${appError.cause.message}`);
}Application Error: Could not retrieve user abc-123. Caused by: TypeError: Failed to fetch: Network unreachable
A generic `Error` is thrown, but it wraps the original `TypeError` using `cause`. This allows the top-level `catch` to present a user-friendly message while still having access to the detailed underlying error for debugging.
Chaining multiple errors
function parseConfig(jsonString) {
try {
return JSON.parse(jsonString);
} catch (jsonErr) {
throw new Error('Invalid configuration format.', { cause: jsonErr });
}
}
function loadApplication(configPath) {
try {
// Simulate reading a file that's not valid JSON
const rawConfig = '{ "key": "value"'; // Malformed JSON
return parseConfig(rawConfig);
} catch (configErr) {
throw new Error(`Failed to load application configuration from ${configPath}.`, { cause: configErr });
}
}
try {
loadApplication('/app/config.json');
} catch (finalError) {
console.error(`Top-level Error: ${finalError.message}`);
let current = finalError;
while (current.cause) {
current = current.cause;
console.error(` Caused by: ${current.name || 'Error'}: ${current.message}`);
}
}Top-level Error: Failed to load application configuration from /app/config.json. Caused by: Error: Invalid configuration format. Caused by: SyntaxError: Expected '}' after property list in JSON at position 16
This example demonstrates a chain of three errors: a `SyntaxError` from `JSON.parse`, wrapped by an 'Invalid configuration' error, which is then wrapped by a 'Failed to load application' error. The loop iterates through the `cause` property to reveal the full chain.
Accessing `Error.cause` in custom error classes
class DataAccessError extends Error {
constructor(message, options) {
super(message, options);
this.name = 'DataAccessError';
}
}
function queryDatabase() {
try {
throw new Error('SQL connection failed.');
} catch (dbError) {
throw new DataAccessError('Failed to access database.', { cause: dbError });
}
}
try {
queryDatabase();
} catch (err) {
console.error(`Error: ${err.name}: ${err.message}`);
if (err.cause) {
console.error(` Original cause: ${err.cause.name}: ${err.cause.message}`);
}
}Error: DataAccessError: Failed to access database. Original cause: Error: SQL connection failed.
Custom error classes can also leverage `Error.cause` by passing the `options` object to `super()`. This allows for type-specific error handling while still preserving the original cause.
Debug faster
Common Errors
Forgetting the `{ cause: ... }` object syntax
Cause: Passing the `cause` directly as a third argument or as part of the message string, rather than within the `options` object as `{ cause: originalError }`.
Fix: Ensure that the `cause` is always provided as a property of the second argument (the options object) to the `Error` constructor: `new Error(message, { cause: originalError })`.
const original = new Error('Original');
// new Error('New error', original); // Incorrect syntax, original will be ignored
const newError = new Error('New error', { cause: original }); // CorrectRuntime support
Compatibility
Source: MDN Web Docs
Common questions
Frequently Asked Questions
Allows associating a new error with an underlying original error, creating a chain of errors for better debugging context.
message: A human-readable description of the new error. options.cause: The underlying error that caused the current error. Can be any value, but typically an `Error` object.
Forgetting the `{ cause: ... }` object syntax: Ensure that the `cause` is always provided as a property of the second argument (the options object) to the `Error` constructor: `new Error(message, { cause: originalError })`.