Express.js Error Handling
No matter how carefully you write code, errors will happen. Network issues, invalid user input, database connection problems – your Express app needs to handle these gracefully. Proper error handling and debugging practices separate professional applications from amateur ones.
Types of Errors in Express
| Error Type | Example |
|---|---|
| Operational Errors | Invalid input, database timeout, file not found |
| Programming Errors | Bug in code, undefined variable, null reference |
| System Errors | Out of memory, disk full, network down |
Error handling is like airbags in a car – you hope you never need them, but you're glad they're there when something goes wrong.
Basic Error Handling Patterns
1. Try/Catch with Async/Await
app.get('/users/:id', async (req, res, next) => { try { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); } catch (err) { <!-- Pass error to Express error handler --> next(err); }});2. Wrapper Function to Avoid Try/Catch Repetition
const catchAsync = (fn) => { return (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); };};
<!-- Use it like this -->app.get('/users/:id', catchAsync(async (req, res) => { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user);}));Error Handling Middleware
Express has special middleware for errors – it takes four parameters `(err, req, res, next)`. Place it at the end of your middleware chain.
<!-- Custom error class -->class AppError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; this.isOperational = true; Error.captureStackTrace(this, this.constructor); }}
<!-- Error handling middleware -->app.use((err, req, res, next) => { <!-- Default values --> err.statusCode = err.statusCode || 500; err.message = err.message || 'Internal Server Error'; <!-- Log error for debugging (but not in production?) --> console.error('ERROR 💥:', err); <!-- Send different responses in development vs production --> if (process.env.NODE_ENV === 'development') { res.status(err.statusCode).json({ error: err.message, stack: err.stack, isOperational: err.isOperational }); } else { <!-- Production: don't leak error details --> if (err.isOperational) { res.status(err.statusCode).json({ error: err.message }); } else { <!-- Programming or unknown error --> res.status(500).json({ error: 'Something went wrong' }); } }});404 Handler
This goes before your error handler but after all routes.
app.use((req, res, next) => { return next(new AppError(`Can't find ${req.originalUrl} on this server!`, 404));});Debugging Techniques
1. Console.log (Basic but Effective)
console.log('Request body:', req.body);console.log('User from DB:', user);2. Debug Module
npm install debugconst debug = require('debug')('app:server');
app.listen(3000, () => { debug('Server running on port 3000');});
<!-- Run with: DEBUG=app:* node app.js -->3. Using Node.js Inspector
node --inspect app.js<!-- Then open chrome://inspect in Chrome -->4. VS Code Debugger
Create a `.vscode/launch.json` configuration:
{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Launch Program", "skipFiles": ["/**"], "program": "${workspaceFolder}/app.js" } ]}Best Practices Summary
- Use try/catch with async/await or wrap async functions.
- Create a custom error class to distinguish operational errors.
- Always pass errors to Express with `next(err)`.
- Have a centralized error handler at the end of your middleware.
- Don't leak error details in production.
- Log errors for debugging and monitoring.
- Handle 404 errors before your main error handler.
Two Minute Drill
- Use try/catch with async/await and pass errors to `next()`.
- Create a wrapper like `catchAsync` to avoid repetitive try/catch.
- Error-handling middleware has 4 parameters `(err, req, res, next)`.
- Distinguish between operational and programming errors.
- Use debugging tools: console.log, debug module, Node.js inspector, VS Code debugger.
Need more clarification?
Drop us an email at career@quipoinfotech.com
