Chen Yang

Error Handling with Express.js

I think error handling is a very tricky part of development. When I started as a self-taught Node.js full-stack developer, I know use throw new Error would throw out the errors in the terminal, but I don't know how to let my frontend "know" these errors and show them in the UI for users. I really struggled with this for a while.

In this article, I'll showcase how I deal with error handling in REST API with Express.js.

Catch Errors in Backend

I use a middleware like this:

const errorHandler = (err, req, res, next) => {
  const statusCode = err.statusCode || 500;

  res.status(statusCode).json({
    type: 'error',
    message: err.message,
  });

  next();
};

In the business logic, when there's an error occurred, I handle it this way (code below), use the guard clause concept throw the error, and catch it by the middleware.

router.post('/', (req, res, next) => {
  try {
    // register a new user, but the username is already taken
    if (usernameUsed) {
      const error = new Error('The username is taken.');
      error.statusCode = 409;
      throw error;
    }
  } catch (error) {
    // the error will catched by the middleware above and response as an object:
    // { type: "error", message: "The username is taken." } with 409 status code.
    next(error);
  }
});

Show Error Messages in Frontend

In the front end, I use fetch to communicate with the server. I don't like axios because when there's a non-2xx status code, axios just break and cannot show any message from the server. So the code in the frontend is something like this:

const addNewUser = (userInfo) => {
  return fetch('/register', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(userInfo),
  })
    .then((response) => response.json())
    .then((data) => {
      if (data.type === 'error') {
        // the `type` we defined in the backend middleware
        alert(data.message);
      }
    });
};

Thus, the users could know what is happening thereby adjust their inputs.