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.