Error Handling Antipatterns
Overview
Section titled “Overview”Error handling antipatterns make applications unreliable and hard to debug. They can also expose sensitive information to attackers.
Common Problems
Section titled “Common Problems”1. Swallowing Errors
Section titled “1. Swallowing Errors”Catching exceptions and ignoring them completely.
2. Exposing Internal Errors
Section titled “2. Exposing Internal Errors”Showing stack traces and implementation details to users.
3. Generic Error Handling
Section titled “3. Generic Error Handling”Catching everything with the same handler.
Articles in This Section
Section titled “Articles in This Section”- Error Swallowing - Silent failures
- Error Exposure - Leaking sensitive information
Quick Comparison
Section titled “Quick Comparison”| Antipattern | Problem | Solution |
|---|---|---|
| Error Swallowing | Silent failures | Log and rethrow |
| Error Exposure | Information leakage | Sanitized responses |
| Generic Catch | Lost context | Typed error handling |
Key Principles
Section titled “Key Principles”1. Fail Loudly
Section titled “1. Fail Loudly”// Bad - silent failuretry { await saveData(data)} catch (e) { // ignore}
// Good - fail visiblytry { await saveData(data)} catch (error) { logger.error('Failed to save data', { error, data }) throw new DataPersistenceError('Save failed', { cause: error })}2. Separate Internal and External Errors
Section titled “2. Separate Internal and External Errors”// Internal: full details for logginglogger.error('Database connection failed', { host: config.db.host, error: error.message, stack: error.stack,})
// External: safe message for usersres.json({ error: 'Unable to process request', code: 'SERVICE_UNAVAILABLE',})3. Use Typed Errors
Section titled “3. Use Typed Errors”class ValidationError extends Error { constructor(field, message) { super(message) this.field = field this.code = 'VALIDATION_ERROR' }}
class NotFoundError extends Error { constructor(resource, id) { super(`${resource} not found: ${id}`) this.code = 'NOT_FOUND' }}