Error Handling

Robust error handling is what separates a prototype from a production-ready application. In Node.js, uncaught errors can crash the entire process, so proper management is crucial.

1. Using Try-Catch

For synchronous code or async/await, use the traditional try...catch block.

try {
  const data = JSON.parse(invalidJson);
} catch (error) {
  console.error('Caught an error:', error.message);
}

2. Express Error Middleware

Express has a built-in error handler, but you can create custom ones. Error-handling middleware always takes four arguments.

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    success: false,
    message: err.message || 'Internal Server Error'
  });
});

3. Global Error Listeners

To prevent your app from crashing on unexpected errors, listen for global events on the process object.

// Handle Uncaught Exceptions
process.on('uncaughtException', (err) => {
  console.error('There was an uncaught error', err);
  process.exit(1); // Standard practice: exit and let PM2 restart
});

// Handle Unhandled Promise Rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});
Pro Tip: Use a library like http-errors to create consistent error objects with status codes throughout your application.