Exception Filters
Exception filters catch errors thrown during a request and shape the error response.
throw new NotFoundException('message')An exception filter is the last layer. It catches exceptions thrown anywhere in the request and controls the response the client receives.
Built-in handling
Nest has a global filter that turns HttpException instances into proper JSON error responses. You throw exceptions like NotFoundException and Nest formats them.
Custom filters
Implement ExceptionFilter and use @Catch() to handle specific exception types, for example to log errors or return a custom shape.
Example
import { Controller, Get, NotFoundException } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get(':id')
findOne() {
// Nest turns this into a 404 JSON response automatically
throw new NotFoundException('User not found');
}
}When to use it
- A developer creates an HttpExceptionFilter that formats all HTTP exceptions into a consistent { statusCode, message, timestamp } JSON body.
- A team writes a TypeOrmExceptionFilter that catches database unique-constraint errors and returns a user-friendly 409 Conflict response.
- An engineer applies an exception filter only to a single controller to handle domain-specific errors differently from the global error format.
More examples
Custom HTTP exception filter
Catches all HttpException instances and returns a formatted error body with statusCode, message, and timestamp.
import { 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 res = ctx.getResponse<Response>();
const status = exception.getStatus();
res.status(status).json({
statusCode: status,
message: exception.message,
timestamp: new Date().toISOString(),
});
}
}Apply filter at controller level
Applies the exception filter to all routes in CatsController using @UseFilters at the class level.
import { Controller, Get, UseFilters } from '@nestjs/common';
import { HttpExceptionFilter } from './http-exception.filter';
@Controller('cats')
@UseFilters(HttpExceptionFilter)
export class CatsController {
@Get()
findAll() {
throw new ForbiddenException();
}
}Global exception filter
Registers the exception filter globally in bootstrap so every unhandled HttpException across the entire app is caught and formatted.
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(3000);
}
bootstrap();
Discussion