Prompt
When handling errors, always ensure the original error context is preserved and properly surfaced. Error information should never be silently swallowed in try/catch blocks, as this makes debugging extremely difficult and can lead to unexpected system behavior.
There are two recommended approaches to preserving error context:
- Use the standard
error.causeproperty to maintain error chains:
try {
// Original operation
const result = func(error, reply.request, reply);
// Process result...
} catch (err) {
// Preserve original error context
if (!Object.prototype.hasOwnProperty.call(err, 'cause')) {
err.cause = error; // Link the original error as the cause
} else {
// Log when unable to set cause to avoid losing context
logger.warn({
err: error,
parentError: err,
message: 'Original error cannot be linked as cause'
});
}
// Propagate the error with context preserved
throw err;
}
- In asynchronous code, ensure proper promise rejection handling:
// BAD: Double resolution if error occurs
sget(options, (err, response, body) => {
if (err) reject(err)
resolve({ response, body }) // Still runs after reject!
})
// GOOD: Return after rejection to prevent double resolution
sget(options, (err, response, body) => {
if (err) {
reject(err)
return // Important! Prevents executing the resolve
}
resolve({ response, body })
})
Remember that proper error handling includes validation of your error conditions themselves. Be careful with falsy checks that might incorrectly handle empty strings or zero values as error conditions.