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;

    type: 'error',
    message: err.message,


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.'/', (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.

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

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