How to Use Exception Filters in NestJS for Error Handling

Updated: January 1, 2024 By: Guest Contributor Post a comment

Understanding Exception Filters in NestJS

Exception filters in NestJS are a powerful feature that allows developers to handle exceptions that occur during the execution of HTTP requests. These filters give you fine-grained control over error handling, allowing for customized responses to clients when an error occurs. The reason you might encounter errors related to exception filters in your Node.js project when using NestJS could stem from inappropriate usage, misconfiguration, or a misunderstanding of how these filters are supposed to be implemented or applied.

Handling Exceptions With Filters

In NestJS, exception filters can be used to catch unhandled exceptions and apply a particular logic such as logging or formatting error responses. It’s crucial to know that NestJS comes with built-in exceptions (like NotFoundException, BadRequestException, etc.) that you can use to trigger common HTTP error statuses. However, the generic HttpException can be extended or customized, which is where filters come into play.

To create your custom exception filter in NestJS using the latest TypeScript syntax, you should implement the ExceptionFilter interface and decorate your class with the @Catch decorator, optionally passing the exceptions you want to catch.

Creating a Custom Exception Filter

Here’s an example of a simple custom exception filter in NestJS.

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';

@Catch(HttpException)
class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const request = ctx.getRequest();
    const status = exception.getStatus();
    const message = exception.getResponse();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        path: request.url,
        message: message
      });
  }
}

Once you’ve defined your filter, you can apply it in several ways:

Controller-Scope

If you want to use the filter for a specific controller, you can attach it using the @UseFilters decorator on your controller class or specific handler methods.

import { Controller, UseFilters } from '@nestjs/common';

@Controller('cats')
@UseFilters(new HttpExceptionFilter())
export class CatsController {}

Global-Scope

To apply the filter to every route across your application, it can be registered at the application level. When setting up your main.ts, add the filter instance to the application’s filters.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './http-exception.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalFilters(new HttpExceptionFilter());
  await app.listen(3000);
}
bootstrap();

Troubleshooting Common Issues

If you encounter issues when using exception filters, these might be due to several reasons:

  • Attempting to send a response when the response has already been sent by another part of the application can lead to errors. Ensure that the filter is the only part sending the response.
  • Forgetting to provide an instance of your custom filter to the decorator or when setting the application-level filter.
  • Not catching the specific exception within your filter’s @Catch() decorator if you have designed it to handle particular exceptions only.

By adequately creating custom exception filters and ensuring their correct placement within your application’s context, you can effectively manage error handling in NestJS projects.