
Chaining Contextual Exceptions with JavaScript Error Cause
In layered application architectures—such as API clients, database access layers, and UI state managers—catching a low-level error (e.g. TypeError: Failed to fetch) and rethrowing a high-level domain error (e.g. UserNotFoundError) historically erased the original stack trace and error message.
ES2022 introduced the cause property to the Error constructor, allowing developers to chain contextual errors while preserving full causal stack traces.
Example
async function fetchUserProfile(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (err) {
throw new Error(`Failed to load profile for user ${userId}`, { cause: err });
}
}
Implementation
Logging the top-level error retains the full diagnostic ancestry:
try {
await fetchUserProfile('user_42');
} catch (error) {
console.error(error.message); // "Failed to load profile for user user_42"
console.error('Caused by:', error.cause); // Original network error or HTTP status
}
Main Point: The Error({ cause }) feature enables clean layered error handling without destroying diagnostic stack traces.
Credits
Photo by Kalist Strzalkowski on Unsplash