When building modern backend applications with NestJS, effective error handling is critical to maintaining a smooth user experience. Users should be informed of issues without exposing sensitive information. NestJS provides a structured way to achieve this through Exception Filters. In this post, we will explore how to create and use Exception Filters in NestJS, allowing for robust error management in your applications.
Exception Filters in NestJS are a type of middleware designed to handle exceptions thrown from the application. By default, NestJS automatically catches unhandled exceptions and returns a simple error response. However, when you want to provide more context or have specific logic for certain types of exceptions, using Exception Filters is the way to go.
When an exception is thrown in a NestJS application, the framework goes through the following process:
Let’s create a custom exception filter to demonstrate how they work. To begin, we need to create a filter using the ExceptionFilter
interface.
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; import { Response } from 'express'; @Catch(HttpException) // This will catch only HttpExceptions export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const status = exception.getStatus(); const errorResponse = exception.getResponse(); // Format your error response response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: ctx.getRequest().url, ...errorResponse, }); } }
@Catch(HttpException): This decorator tells NestJS that this filter is specific to catching HttpException
. You can modify this to catch any other exceptions or create multiple filters for different types.
ArgumentsHost: This is a utility provided by NestJS to access the context of the exception. It allows us to get information about the request and response.
Response Handling: We grab the response object and build a structured error response that includes the status code, timestamp, and the path of the request. This gives clients enough information without breaching security.
Once your filter is created, you need to use it in your application. You can apply the filter globally, to a specific controller, or even to specific routes.
To use the filter globally, modify the main.ts
file:
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();
To apply the filter to a specific controller, use the @UseFilters()
decorator:
import { Controller, Get, UseFilters } from '@nestjs/common'; import { HttpExceptionFilter } from './http-exception.filter'; @Controller('test') @UseFilters(HttpExceptionFilter) // Apply for specific controller export class TestController { @Get() findAll() { throw new HttpException('Test error', 400); // This will be caught by the filter } }
You may want to handle other types of exceptions or implement additional logic based on the exception type. It's easy to customize the filter by extending the code we previously created:
@Catch() export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const status = exception instanceof HttpException ? exception.getStatus() : 500; // Default to Internal Server Error for non-HTTP exceptions const errorResponse = typeof exception === 'object' && 'message' in exception ? exception : { message: 'Internal server error' }; // Fallback message response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: ctx.getRequest().url, ...errorResponse, }); } }
In this customized filter, we catch all exceptions and check if it's a HttpException
or default to a 500 status code. This makes it a robust catch-all filter that can handle various scenarios and types of exceptions.
By utilizing Exception Filters in NestJS, we can ensure that our applications not only handle errors gracefully but also provide meaningful feedback to clients. This structured approach enhances both the clarity and maintainability of our code, allowing us to build better and more reliable applications. As you continue developing with NestJS, consider implementing custom exception filters to fit your application's specific needs.
Remember, effective error handling is key to creating resilient applications that users will appreciate!
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS
10/12/2024 | NestJS