Handling custom error types in Express.js
Tags: javascript, node
Published: 2019-11-27 13:19:34

In 2 previous posts we explained how to [create a custom error type](https://dev.to/lvidakovic/custom-error-types-in-node-js-491a) and [created a few custom HTTP errors](https://dev.to/lvidakovic/from-custom-error-types-to-a-custom-error-subtype-3nkf) we'll use to automatically send HTTP response to an error using [Express.js](https://expressjs.com/) error middleware and util functions. Our custom error types allow us to generically handle well-defined types of failure and auto-respond with appropriate HTTP status code and JSON data, if any is to be sent to the client.

To explain the direction we are headed, well known errors will be handled this way:

```javascript
app.get('/user/me', function(req, res) {
  db.getUser(...)
    .then(user => res.json(user))
    .catch(res.respond.notFound)
    // or
    .catch(error => res.respond.notFound(error, {reason: 'User ID not found'}))
})
```

Notice error handler functions passed to the `.catch` methods. That is the API we want to construct to support automatic error handling, but also allow to send some context data alongside error in the HTTP response.

To get there, first we need to have something that will expose `res.respond` API for every response. Ideal job for a tiny middleware function:

```javascript
function attachResponder(req, res, next) {
    res.respond = createResponder(req, res, next);
    next();
}
```

We probably want our middleware to run before all other request handlers to expose the respond API for all requests. So it'll need to be set before any other handlers on a Express.js Router:

```javascript
app.use(attachResponder)
// ...
app.get('/user/me', function(req, res) {
// ...
```

Great, logic to have `res.respond` available on every request is here. But we haven't defined the logic behind its interface. Here it is:

```javascript
function createResponder(req, res, next) {
  const responder = {
    _forwardError(error, ErrorClass = Error, data) {
      const errorMessage = error instanceof Error ? error.message : error;
      const errorToForward = new ErrorClass(errorMessage, data);
      // forwards error to an error handler middleware
      next(errorToForward);
    },

    badRequest(error, data) {
      return responder._forwardError(error, HttpBadRequest, data);
    },
    notFound(error, data) {
      return responder._forwardError(error, HttpNotFound, data);
    },
    internalServerError(error, data) {
      return responder._forwardError(error, HttpInternalServer, data);
    }
  };

  return responder;
}

```

Calling this function inside middleware function attaches responder object to `res.respond`. Responder itself exposes 3 meaningful methods: *badRequest*, *notFound* and *internalServerError*. All 3 can be called without parameters, only with Error instance, only with error explanation(string) or with error and additional data we want to pass in the response.
*_forwardError* method mainly serves for code reuse. It resolves the error type and creates custom error type with appropriate message and data. That error is then forwarded to an Express.js error handler middleware.  

Express.js error handling middleware is always declared as the last middleware on an Express.js Router. It needs to be able to receive and handle all the errors previous middleware functions might have thrown. It's pretty simple to create one that just ends the response with HTTP 500 error for every error it catches:

```javascript
function errorHandler(error, req, res, next) {
  res.sendStatus(httpResponseCodes.INTERNAL_SERVER_ERROR)
}
```

We'd attach it to an Express.js app like so:

```javascript
app.use(attachResponder)
// ...
// app.get('/user/me', function(req, res) {
// ...
app.use(errorHandler)
```

But we don't want to respond with `500 – Internal server error` every time. Especially since we have our custom error types and their subtype. We can now do all sorts of smart logic inside this handler. We can recognize our custom errors, and since all of them have a status code and a message, just respond with that information. If you don't remember the custom error types we've defined you can [look them up in the previous post](https://dev.to/lvidakovic/from-custom-error-types-to-a-custom-error-subtype-3nkf).

```javascript
function errorHandler(error, req, res, next) {
  if (error instanceof HttpError) {
    res.status(error.statusCode).json(error.data)
  } else {
    res.sendStatus(httpResponseCodes.INTERNAL_SERVER_ERROR)
  }
}
```

We've reached the functional API we wanted from the start and we now have a logic that automatically processes well-defined error types and finishes the response gracefully. If we continued to add another error types that fall under the *HttpError* subtype it would all end up being automatically handled for us inside error handler middleware. Additional benefit of our custom errors going through the single point is that it lends itself great for logging/monitoring purposes. All other, generic errors in this case would just end up as an HTTP 500 error response.

**Idea:**
Responder API could be further extended to provide a means of responding to all kinds of request, even the successful ones. That is all omitted from this posts for the sake of brevity.