Back to Tutorials
Node.js
20 min read
Sahasransu Satpathy
4/25/2026

Error Handling in Node.js

Learn how to handle errors effectively in Node.js applications using try/catch, middleware, and best practices

Introduction

Proper error handling is crucial in Node.js applications to ensure reliability and maintainability. This guide covers synchronous and asynchronous error handling, using try/catch, middleware, and best practices.


Step 1: Synchronous Error Handling

Wrap code in try/catch blocks:

try {
  const result = riskyOperation();
  console.log(result);
} catch (error) {
  console.error("An error occurred:", error.message);
}

Step 2: Asynchronous Error Handling

For asynchronous functions (Promises / async-await):

// Using Promises
asyncFunction()
  .then(result => console.log(result))
  .catch(err => console.error("Promise error:", err));

// Using async-await
async function fetchData() {
  try {
    const data = await getDataFromAPI();
    console.log(data);
  } catch (error) {
    console.error("Async error:", error.message);
  }
}

Step 3: Error Handling in Express.js

Express provides error-handling middleware:

const express = require('express');
const app = express();

// Regular route
app.get('/', (req, res) => {
  throw new Error("Something went wrong!");
});

// Error-handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ message: err.message });
});

app.listen(3000, () => console.log("Server running on port 3000"));

Step 4: Handling Asynchronous Errors in Express

For async routes, wrap in try/catch or use a wrapper function:

app.get('/data', async (req, res, next) => {
  try {
    const data = await fetchDataFromDB();
    res.json(data);
  } catch (error) {
    next(error); // Pass error to middleware
  }
});

Step 5: Custom Error Classes

Create custom error classes for better control:

class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    this.isOperational = true;
  }
}

app.get('/custom-error', (req, res, next) => {
  next(new AppError("Custom error occurred", 400));
});

Step 6: Best Practices

  • Always handle uncaught exceptions and unhandled rejections:
process.on('uncaughtException', (err) => {
  console.error("Uncaught Exception:", err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error("Unhandled Rejection:", reason);
});
  • Return meaningful error messages to clients.
  • Log errors for debugging but avoid exposing sensitive info.
  • Use HTTP status codes consistently.

Conclusion

By following these practices, you can handle errors gracefully in Node.js, keeping your application robust and easier to maintain.


SEO Suggestions:

  • Main keywords: Node.js error handling, Express.js error handling, async errors, try/catch Node.js, error middleware
  • Meta description: Learn how to handle errors effectively in Node.js and Express.js applications with best practices, async handling, and custom error classes.
  • Catchy title suggestions: "Master Error Handling in Node.js – Beginner to Advanced", "Node.js Error Handling Guide 2026"

Previous Tutorial

Browse All Tutorials