domains / / fastify/fastify
Preserve error context
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.
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.