How to Use Error Handler Middleware with Express.js and TypeScript
Tags: typescript, node, api, express
Published: 2021-10-07 13:24:51

---
title: How to Use Error Handler Middleware with Express.js and TypeScript
published: true
date: 2021-06-30 13:03:43 UTC
tags: #typescript, #node, #api, #express
canonical_url: https://www.becomebetterprogrammer.com/how-to-use-error-handler-middleware-with-express-js-and-typescript/?utm_source=rss&utm_medium=rss&utm_campaign=how-to-use-error-handler-middleware-with-express-js-and-typescript
---

![](https://i2.wp.com/www.becomebetterprogrammer.com/wp-content/uploads/2021/06/How-to-Use-Error-Handler-Middleware-with-Express.js-and-TypeScript-1.png?resize=640%2C360&ssl=1)

## What is an Error Handler in Express.js?

Error handlers in Express.js are in charge of catching and handing errors that happen during runtime. By default, Express.js provides with a built-in by default.

### How Does The Error Handler Work in Express.js?

Whenever there is an error occurring in the server, unless you have a custom error handler, Express.js catches the error and sends a response to the client with the error message using its default error handler. The reason Express.js is eager to catch all errors is not only handling properly the errors, but also to correctly empty out unused resources after the application starts running again.

In other words, Express.js is preventing the server from having memory leaks and properly “garbage collects” objects once an API endpoint request is handled by a function.

Let’s explain using an example. Let’s say we have attached a handler function a simple API endpoint.

```typescript
	app.get('/car/model', function (req: express.Request, res: express.Response) {
	  const car = { model: 'Santa Fe', year: 2010, brand: 'Hyundai' };
	 
	  res.send(`The car model is ${car.model}`);	});

```

Besides the fact of returning a message with car model, let’s dig a little deeper of what is going on.

We created a **car** variable which contains a car object. We are allocating memory space every time we create a variable. As soon as we send a response back to the client, we are no longer needing the **car** variable. However, in theory **car** variable still uses memory space.

_Does it mean we are loading up the memory every time we send a response to the client?_

When incorrectly handled, yes. We reduce the memory space by not correctly freeing up that memory space. In other words, this is what we call memory leaks.

But! Express.js is protecting us from suffering memory leak issues by using a default error handler.

### What Does the Error Handler Have to Do with Preventing from Suffering Memory Leaks?

In order to understand how error handlers are helping from Express.js application from crashing, we need to first understand how the Node.js engine works.

If you didn’t know, Node.js uses [V8 engine](https://v8.dev/). V8 engines provides with a built-in garbage collector to manage memory space which leads into a better performance and takes away that extra work from developers.

If you want to understand how the garbage collection work using the V8 engine in depth, I recommend you to [read the article written on the V8 engine website](https://v8.dev/blog/free-garbage-collection). In short, the V8 engine determines memory as _dead_ or _alive,_ meaning if a memory spaces is used, then it is _alive._ If it is not longer used, then it is _dead._ Those with the _dead_ status are eligible for garbage collection.

If we go back to the example of the API endpoint using a simple handler function, you will notice that the function is scoped. Once we send a response to the client, the function and any scoped variables are no longer used, making them eligible under the V8’s garbage collection engine.

In the case we force an error in the handler function, such as:

```typescript
	app.get('/car/model', function (req: express.Request, res: express.Response) {
	  const car = { model: 'Santa Fe', year: 2010, brand: 'Hyundai' };
	 
	  // forcing to trigger an error
	  car.model();
	 
	  res.send(`The car model is ${car.model}`);
	});

```

And there were no error handlers, the client would never get a response in first place. Also, the request will “hang” on, meaning that our handler function would be using _alive_ memory. Since this memory is _alive,_ the V8 engine garbage collection would not work, causing memory leaks in the server.

### Are There Problems with Using Express.js Default Error Handler?

There are no problems with the default error handler. However, it is important for you to understand some concepts. Let’s say we use our previous code example to manually force to trigger an error. I encourage you to make a request to the endpoint. You should get an error response, which it is expected.

However, this error response is not user friendly. It is rather technical and provides with the stack information about the server, such as the folder structure of the API. This information is beneficial if you are troubleshooting errors during development stages, but dangerous if this were to happen in production environments.

Fortunately, Express.js can prevent displaying any sensitive information from errors in the production stages. To make this work, you should make sure the **NODE\_ENV** var is set to “production” prior to creating the express application.

### Why Should I Implement a Custom Error Handler?

There can be different reasons why you would want to implement a custom error handler. For example, there projects that don’t set **NODE\_ENV** as “production” in production stages. This could lead to leaking sensitive information about the system if not properly handled.

There are other projects that require to send a specific error object format whenever some unexpected error occurs.

### How to Write a Custom Error Handler in Express.js using TypeScript?

Error handler middleware work very similar to any other middleware. However, there are a few things to take into consideration.

When developing an application-level or a route-level middleware, the handler function expects to receive three arguments: **Request** , **Response** , and **NextFunction**. In the case of developing a custom handler error, the handler function is expected to have four arguments. **ErrorRequestHandler** , **Request** , **Response** , and **NextFunction.**

Let’s go ahead an create our own custom error handler. In our case, we want to send custom error messages in case we want to provide meaningful information to the client about why the server cannot execute a certain process. One example could be of reading the records of a spreadsheet send by the client containing invalid data type for a specific column. Therefore, our first step is to create a **CustomError** object.

#### 1. Create CustomError Object

First, create a **custom-error.model.ts** file in the following folder location: **src/api/models.** Once it is created, we are going to generate a class and export it.

```typescript
	export class CustomError {
	  message!: string;
	  status!: number;
	  additionalInfo!: any;
	 
	  constructor(message: string, status: number = 500, additionalInfo: any = {}) {
	    this.message = message;
	    this.status = status;
	    this.additionalInfo = additionalInfo
	  }
	}

```

#### 2. Create Custom Error Handler Middleware

Create a file called **error-handler.middleware.ts**  inside the **src/api/middlewares** folder. Once created, we are going to add the following logic:

```typescript
	import { Request, Response, NextFunction } from 'express';
	import { CustomError } from './../models/custom-error.model';
	 
	/**
	 * Custom error handler to standardize error objects returned to 
	 * the client
	 * 
	 * @param err Error caught by Express.js
	 * @param req Request object provided by Express
	 * @param res Response object provided by Express
	 * @param next NextFunction function provided by Express
	 */
	function handleError(
	  err: TypeError | CustomError,
	  req: Request,
	  res: Response,
	  next: NextFunction
	) {
	  let customError = err;
	 
	  if (!(err instanceof CustomError)) {
	    customError = new CustomError(
	      'Oh no, this is embarrasing. We are having troubles my friend'
	    );
	  }
	 
	  // we are not using the next function to prvent from triggering 
	  // the default error-handler. However, make sure you are sending a 
	  // response to client to prevent memory leaks in case you decide to 
	  // NOT use, like in this example, the NextFunction .i.e., next(new Error())
	  res.status((customError as CustomError).status).send(customError);
	};
	 
	export default handleError; 
```

#### 3. Attach Custom Error Handler as The Last Middleware to Use

Open the **index.ts** file. Then, import the custom handler and add it to the application as the last middleware. In other words, make sure to use the last **app.use** for the error handler middleware. If you are following the **[_Learn How to Use TypeScript With Node.js and Express.js_](https://www.becomebetterprogrammer.com/learn-how-to-use-typescript-with-node-js-and-express-js/)** series, your **index.ts** file should look like the following:

```typescript

import express from 'express';
import compression from 'compression';
import helmet from 'helmet';
import bodyParser from 'body-parser';
import cors from 'cors';
import { generateToken } from './api/utils/jwt.utils';
 
import routes from './api/routes';
 
import logger from './api/middlewares/logger.middleware';
import errorHandler from './api/middlewares/error-handler.middleware';
 
const app = express();
const port = 3000;
 
// Only generate a token for lower level environments
if (process.env.NODE_ENV !== 'production') {
  console.log('JWT', generateToken());
}
 
// compresses all the responses
app.use(compression());
 
// adding set of security middlewares
app.use(helmet());
 
// parse incoming request body and append data to `req.body`
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
 
// enable all CORS request 
app.use(cors());
 
// add logger middleware
app.use(logger);
 
app.use('/api/', routes);
 
// add custom error handler middleware as the last middleware
app.use(errorHandler);
 
app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
}); 

```

#### 4. Test Custom Handler

First, force an error in one of the function handlers for any of your API endpoints. In our case, we are going to modify the **getTeams** function we have in the **teams.controller.ts** file.

```typescript

export const getTeams = (req: Request, res: Response) => {
  const test = {};
  //@ts-ignore
  test.nonExistingMethod();
 
  res.send(TEAMS);
}; 

```

Once, me make a request to _PORT/api/teams/_ we should get the following error object:

```json

{
    "message": "Oh no, this is embarrasing. We are having troubles my friend",
    "status": 500,
    "additionalInfo": {}
}

```

Now, let’s use the **CustomError** object and throw a **CustomError** instance inside our function handler instead.

```typescript

import { Request, Response } from 'express';
import { CustomError } from './../models/custom-error.model';
 
const TEAMS = [
  { id: 1, name: 'Real Madrid', league: 'La Liga' },
  { id: 2, name: 'Barcelona', league: 'La Liga' },
  { id: 3, name: 'Manchester United', league: 'Premier League' },
  { id: 4, name: 'Liverpool', league: 'Premier League' },
  { id: 5, name: 'Arsenal', league: 'Premier League' },
  { id: 6, name: 'Inter', league: 'Serie A' },
  { id: 7, name: 'Milan', league: 'Serie A' },
  { id: 8, name: 'Juventus', league: 'Serie A' },
];
 
export const getTeams = (req: Request, res: Response) => {
  throw new CustomError('forgot something?', 400, 'you can do better than that');
  res.send(TEAMS);
};

```

The expected error object result should be the following:

```json

{
    "message": "forgot something?",
    "status": 400,
    "additionalInfo": "you can do better than that"
}

```