🔗 Don’t Lose the Original Error
Throwing new Error() loses original stack. Error cause chains errors. See full context.
📝 Without Error Cause (Lost Context)
try {
await fetchUser(userId);
} catch (err) {
throw new Error(`Failed to get user ${userId}`);
// Original error stack lost!
}
✅ With Error Cause (Full Context)
try {
await fetchUser(userId);
} catch (err) {
throw new Error(`Failed to get user ${userId}`, { cause: err });
// Original error accessible via error.cause
}
// Multi-level chain
try {
// Database error
} catch (dbError) {
try {
// Try fallback
} catch (fallbackError) {
throw new Error(`Both primary and fallback failed`, {
cause: { primary: dbError, fallback: fallbackError }
});
}
}
✅ Real-World Example
async function getOrderWithDetails(orderId) {
try {
const order = await fetchOrder(orderId);
const user = await fetchUser(order.userId);
const products = await fetchProducts(order.productIds);
return { order, user, products };
} catch (err) {
// Add context at each level
throw new Error(`Failed to load order ${orderId}`, { cause: err });
}
}
// Later in error handler
try {
await getOrderWithDetails(123);
} catch (err) {
console.error(err.message); // "Failed to load order 123"
console.error(err.cause); // Original fetch error
}
💡 Benefits
- Preserves original error stack trace
- Adds context without losing details
- Better debugging in production
- Logging services show full chain
“API error: ‘Failed to fetch user’. No clue why. Added error cause: original DB connection error. Fixed in 5 minutes. Error cause should be standard everywhere.”
