Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
Chain errors together to preserve the original error context! When catching and re-throwing errors, you can now attach the original error as the cause - making debugging much easier!
try {
// This might fail
JSON.parse('invalid json');
} catch (error) {
// Re-throw with context, preserving original error
throw new Error('Failed to parse config', {
cause: error
});
}
// Output:
// Error: Failed to parse config
// Caused by: SyntaxError: Unexpected token i in JSON...async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
// Add context about what we were doing
throw new Error(
`Failed to fetch user ${userId}`,
{ cause: error }
);
}
}
// Usage
try {
await fetchUserData(123);
} catch (error) {
console.error(error.message); // 'Failed to fetch user 123'
console.error(error.cause); // Original network/parse error
}async function loadConfig() {
try {
return await readFile('config.json');
} catch (error) {
throw new Error('Config read failed', { cause: error });
}
}
async function initializeApp() {
try {
const config = await loadConfig();
return setupApp(config);
} catch (error) {
throw new Error('App initialization failed', { cause: error });
}
}
// Usage shows full error chain
try {
await initializeApp();
} catch (error) {
console.error(error.message); // 'App initialization failed'
console.error(error.cause.message); // 'Config read failed'
console.error(error.cause.cause); // Original file error
}function logErrorChain(error) {
const errors = [];
let currentError = error;
// Traverse the error chain
while (currentError) {
errors.push({
message: currentError.message,
name: currentError.name,
stack: currentError.stack
});
currentError = currentError.cause;
}
console.log('Error Chain:');
errors.forEach((err, index) => {
console.log(` ${index + 1}. ${err.name}: ${err.message}`);
});
}
// Usage
try {
doSomething();
} catch (error) {
logErrorChain(error);
// Output shows complete error trail
}class DatabaseError extends Error {
constructor(message, options) {
super(message, options);
this.name = 'DatabaseError';
}
}
async function saveUser(user) {
try {
await db.users.insert(user);
} catch (error) {
// Preserve database-specific error details
throw new DatabaseError(
`Failed to save user ${user.id}`,
{
cause: error,
// Can add custom properties too
userId: user.id,
operation: 'insert'
}
);
}
}
// Error handling
try {
await saveUser({ id: 123, name: 'Alice' });
} catch (error) {
if (error instanceof DatabaseError) {
console.error('DB Error:', error.message);
console.error('User ID:', error.userId);
console.error('Original:', error.cause);
}
}See the complete error chain - know exactly what went wrong
Don't lose valuable error information when re-throwing
Standard way to chain errors - no custom properties needed
Link errors together preserving context
See complete error trail
new Error(msg, {cause: err})
Standard error handling