Node.js Error Handling Patterns
Intermediate
Handle errors properly in Node.js — always catch promise rejections, use custom error classes, implement global error handlers, and never swallow errors silently.
File Patterns
**/*.js**/*.mjs**/*.ts
This rule applies to files matching the patterns above.
Rule Content
rule-content.md
# Node.js Error Handling Patterns
## Rule
Every async operation MUST have error handling. Unhandled promise rejections MUST crash the process. Use custom error classes with status codes and operational/programmer error distinction.
## Format
```javascript
// Custom error class
class AppError extends Error {
constructor(message, statusCode, isOperational = true) {
super(message);
this.statusCode = statusCode;
this.isOperational = isOperational;
Error.captureStackTrace(this, this.constructor);
}
}
```
## Good Examples
```javascript
// Custom error hierarchy
class NotFoundError extends AppError {
constructor(resource, id) {
super(`${resource} with id ${id} not found`, 404);
}
}
class ValidationError extends AppError {
constructor(message, errors) {
super(message, 400);
this.errors = errors;
}
}
// Async error handling in Express
app.get("/users/:id", async (req, res, next) => {
try {
const user = await userService.findById(req.params.id);
if (!user) throw new NotFoundError("User", req.params.id);
res.json(user);
} catch (error) {
next(error); // Pass to error middleware
}
});
// Global handlers
process.on("unhandledRejection", (reason) => {
logger.fatal("Unhandled rejection", { reason });
process.exit(1); // Crash — state is unknown
});
process.on("uncaughtException", (error) => {
logger.fatal("Uncaught exception", { error });
process.exit(1);
});
```
## Bad Examples
```javascript
// BAD: Swallowing errors
try {
await riskyOperation();
} catch (error) {
// Silent catch — error disappears
}
// BAD: Generic error messages
throw new Error("Something went wrong"); // Useless for debugging
// BAD: No async error handling
app.get("/users", async (req, res) => {
const users = await db.query("SELECT * FROM users");
// If query fails, Express gets unhandled rejection
res.json(users);
});
```
## Enforcement
- Use express-async-errors or wrapper for automatic next(error)
- Configure Node.js --unhandled-rejections=throw (default in v15+)
- ESLint: no-empty catch blocks
- Structured logging for all caught errorsFAQ
Discussion
Loading comments...