In any application, error handling is critical for ensuring that users receive meaningful feedback when things go wrong. In NestJS, exception filters are a powerful tool that allow you to manage errors in a centralized, consistent way across your entire application.
In this module, we’ll explore how to use exception filters in NestJS to handle errors globally or locally. We’ll look at how to define custom exception filters, use built-in exceptions, and create a unified error-handling strategy for your NestJS application.
Table of Contents
- Introduction
- What are Exception Filters in NestJS?
- Default Error Handling in NestJS
- Creating a Custom Exception Filter
- Using Built-in Exception Filters
- Applying Exception Filters Globally and Locally
- Customizing the Response Format
- Best Practices for Exception Handling
- Conclusion
Introduction
In every application, errors can occur for various reasons: user input issues, server failures, or network problems. Handling these errors in a way that makes sense to users is critical for a good user experience.
NestJS offers a flexible exception filter mechanism that enables you to manage errors consistently across your entire application. Exception filters in NestJS allow you to catch and transform errors before they are sent to the client, ensuring that your application provides clear and informative error messages.
This module will cover the fundamentals of exception filters in NestJS and demonstrate how to set up centralized error handling for your application.
What are Exception Filters in NestJS?
In NestJS, an exception filter is a class responsible for handling and formatting errors. It provides a way to catch unhandled exceptions and return a custom response. Exception filters are particularly useful when you want to:
- Catch exceptions thrown by the framework, such as
HttpException
orBadRequestException
. - Handle application-specific exceptions and format them consistently.
- Implement centralized error-handling logic for your entire application.
Key Concepts of Exception Filters:
- Custom Filters: You can create custom filters to handle specific errors.
- Global and Local Filters: Filters can be applied globally or at the controller or method level.
- Built-in Exception Filters: NestJS provides built-in exception filters to handle standard HTTP errors.
Default Error Handling in NestJS
By default, NestJS uses a built-in exception filter that catches all exceptions, formats them into a consistent response, and sends them to the client.
For example, if you throw a BadRequestException
, NestJS will automatically respond with a 400
HTTP status code and a message:
{
"statusCode": 400,
"message": "Bad Request",
"error": "Bad Request"
}
While this default behavior is useful, you may want to customize error responses to better suit your application’s needs, provide additional information, or log the errors.
Creating a Custom Exception Filter
Creating a custom exception filter allows you to catch specific errors and handle them in a tailored way. Here’s how to create and use a custom exception filter in NestJS:
Step 1: Create a Custom Exception Filter
To create a custom exception filter, you need to implement the ExceptionFilter
interface and the catch
method. The catch
method is responsible for handling the exception.
Here’s an example of a custom exception filter that handles all NotFoundException
errors:
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
import { Response } from 'express';
import { NotFoundException } from '@nestjs/common';
@Catch(NotFoundException)
export class NotFoundExceptionFilter implements ExceptionFilter {
catch(exception: NotFoundException, host: ArgumentsHost) {
const response = host.switchToHttp().getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
message: 'Resource not found',
error: 'Not Found',
});
}
}
Step 2: Use the Custom Exception Filter
You can apply the custom filter either globally or locally.
Apply Filter Globally
To apply the filter globally, modify your main.ts
file as follows:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NotFoundExceptionFilter } from './filters/not-found-exception.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new NotFoundExceptionFilter());
await app.listen(3000);
}
bootstrap();
Apply Filter Locally
To apply the filter only to specific controllers or route handlers, use the @UseFilters()
decorator:
import { Controller, Get, UseFilters } from '@nestjs/common';
import { NotFoundExceptionFilter } from './filters/not-found-exception.filter';
@Controller('users')
@UseFilters(NotFoundExceptionFilter)
export class UserController {
@Get()
findUser() {
throw new NotFoundException();
}
}
Using Built-in Exception Filters
NestJS provides several built-in exception filters that can be used out of the box. These filters handle common HTTP errors such as NotFoundException
, BadRequestException
, UnauthorizedException
, and others.
Example: Using the Built-in HttpException
Filter
NestJS automatically handles all HttpException
errors, including those that extend it, like BadRequestException
, UnauthorizedException
, etc.
Here’s an example of throwing a BadRequestException
:
import { BadRequestException } from '@nestjs/common';
throw new BadRequestException('Invalid input data');
NestJS will automatically respond with a 400
status code and a custom error message:
{
"statusCode": 400,
"message": "Invalid input data",
"error": "Bad Request"
}
These built-in filters can be customized using custom exception filters or by extending NestJS’s exception classes.
Applying Exception Filters Globally and Locally
You can apply exception filters globally or locally in NestJS.
Global Exception Filters
Global exception filters can be applied in the main.ts
file, which affects the entire application. This is useful for handling common errors in a standardized way across all controllers.
app.useGlobalFilters(new NotFoundExceptionFilter());
Local Exception Filters
Local exception filters are applied at the controller or route handler level using the @UseFilters()
decorator. This allows you to handle errors differently depending on the controller or action.
import { Controller, Post, UseFilters } from '@nestjs/common';
import { BadRequestExceptionFilter } from './filters/bad-request-exception.filter';
@Controller('users')
@UseFilters(BadRequestExceptionFilter)
export class UserController {
@Post()
createUser() {
throw new BadRequestException('Invalid user data');
}
}
Customizing the Response Format
By default, NestJS exception filters return a generic error format with statusCode
, message
, and error
fields. You can customize the format of the response by modifying the response object in your custom filter.
Here’s an example of a custom error response format:
@Catch(HttpException)
export class CustomExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const response = host.switchToHttp().getResponse<Response>();
const status = exception.getStatus();
const errorResponse = {
code: status,
message: exception.message,
timestamp: new Date().toISOString(),
path: host.switchToHttp().getRequest().url,
};
response.status(status).json(errorResponse);
}
}
In this example, we’ve added a timestamp
and path
to the error response, giving the client more context about the error.
Best Practices for Exception Handling
- Use Built-in Exception Filters: NestJS provides many useful built-in exception filters that cover common HTTP error cases, such as
NotFoundException
,BadRequestException
, andUnauthorizedException
. - Create Custom Filters for Specific Use Cases: Create custom exception filters when you need to handle specific types of errors or format responses in a unique way.
- Use Global Exception Filters: Apply exception filters globally in
main.ts
to ensure a consistent error-handling strategy across your application. - Handle Specific Errors Locally: Apply exception filters locally when different controllers or routes need different error-handling logic.
- Log Errors for Debugging: Always log errors when possible, especially in production environments, to aid debugging and support.
Conclusion
Exception filters in NestJS provide a flexible and consistent way to handle errors. By creating custom filters or using the built-in ones, you can ensure that your application catches and formats errors in a meaningful way for your users. Centralized error handling improves both the user experience and the maintainability of your application by providing a clear structure for error responses.
Now that you understand how to use exception filters, you can implement a comprehensive error-handling strategy in your NestJS application, ensuring that errors are handled gracefully and consistently.