Skip to main content
Practice Problems

What are exception filters in NestJS?

Exception Filters in NestJS

Exception Filters handle all unhandled exceptions across the application. They catch exceptions and format the HTTP response. NestJS has a built-in global exception filter, but you can create custom filters for fine-grained control.


Built-in HTTP Exceptions

NestJS provides a set of standard exceptions out of the box:

typescript
import { BadRequestException, // 400 UnauthorizedException, // 401 ForbiddenException, // 403 NotFoundException, // 404 ConflictException, // 409 UnprocessableEntityException, // 422 InternalServerErrorException, // 500 BadGatewayException, // 502 } from '@nestjs/common'; throw new NotFoundException('User not found'); throw new BadRequestException('Invalid email format'); throw new ConflictException('Email already registered'); throw new UnauthorizedException();

HttpException Base Class

typescript
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN); // With custom response object throw new HttpException( { status: 403, error: 'Forbidden', hint: 'Contact admin' }, HttpStatus.FORBIDDEN );

Custom Exception

typescript
export class BusinessRuleException extends HttpException { constructor(message: string, rule: string) { super({ message, rule, statusCode: 422 }, HttpStatus.UNPROCESSABLE_ENTITY); } } throw new BusinessRuleException('Cannot delete account with active orders', 'ACTIVE_ORDERS');

Custom Exception Filter

typescript
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger } from '@nestjs/common'; import { Request, Response } from 'express'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { private readonly logger = new Logger(HttpExceptionFilter.name); catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const request = ctx.getRequest<Request>(); const response = ctx.getResponse<Response>(); const status = exception.getStatus(); const exceptionResponse = exception.getResponse(); const error = typeof exceptionResponse === 'string' ? { message: exceptionResponse } : exceptionResponse as object; this.logger.error(`${request.method} ${request.url}${status}`); response.status(status).json({ ...error, statusCode: status, timestamp: new Date().toISOString(), path: request.url, }); } }

Catch-All Filter

typescript
@Catch() // no argument = catch everything export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const request = ctx.getRequest<Request>(); const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR; const message = exception instanceof HttpException ? exception.getResponse() : 'Internal server error'; response.status(status).json({ statusCode: status, message, timestamp: new Date().toISOString(), path: request.url, }); } }

Applying Filters

typescript
// Method-level @Post() @UseFilters(HttpExceptionFilter) create(@Body() dto: CreateUserDto) { ... } // Controller-level @Controller('users') @UseFilters(HttpExceptionFilter) export class UsersController {} // Global — main.ts app.useGlobalFilters(new HttpExceptionFilter()); // Global — module (supports DI, preferred) @Module({ providers: [ { provide: APP_FILTER, useClass: AllExceptionsFilter }, ], })

Summary

Exception filters centralize error formatting. Use the built-in HttpException subclasses for most cases. Create a global @Catch() filter to catch everything, log errors, and return consistent JSON error responses. Register globally via APP_FILTER to benefit from dependency injection.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems