Introduction
Exception filters catch exceptions and transform them into HTTP responses. They provide centralized error handling, logging, and consistent response formatting.
Key Concepts
- @Catch(): Decorator specifying which exceptions to catch
- ExceptionFilter: Interface for filter implementation
- ArgumentsHost: Access to request/response context
Real World Context
Exception filters are essential in production because they standardize error responses across your entire API. Without them, different parts of your application might return errors in different formats, confusing API consumers. A global exception filter also provides a single place for error logging and monitoring integration.
Deep Dive
Basic Exception Filter
typescriptimport { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; import { Response } from 'express'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const status = exception.getStatus(); response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: ctx.getRequest().url, message: exception.message, }); } }
Catch All Exceptions
typescript@Catch() export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR; response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), message: exception instanceof HttpException ? exception.message : 'Internal server error', }); } }
Applying Filters
typescript// Method level @Post() @UseFilters(HttpExceptionFilter) create(@Body() dto: CreateUserDto) {} // Controller level @Controller('users') @UseFilters(HttpExceptionFilter) export class UsersController {} // Global with DI @Module({ providers: [{ provide: APP_FILTER, useClass: AllExceptionsFilter }], }) export class AppModule {}
Common Pitfalls
- Forgetting @Catch(): Without args, catches everything.
- Missing DI: Use APP_FILTER provider for dependency injection.
- Circular logging: Don't throw in exception filters.
Best Practices
- Create a global catch-all filter for unhandled exceptions
- Log errors with full context
- Never expose internal details to clients
Summary
Exception filters provide centralized error handling. Use @Catch() to specify types and apply globally for consistent responses.
Code Examples
typescript
// Global filter with DI support
import { APP_FILTER } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_FILTER,
useClass: AllExceptionsFilter,
},
],
})
export class AppModule {}