Exception Handling
Throw Nest's built-in HTTP exceptions for clean, consistent error responses.
Syntax
throw new BadRequestException('message')Nest provides a family of exception classes that map to HTTP status codes. Throwing one produces a properly formatted JSON error automatically.
Built-in exceptions
| Exception | Status |
|---|---|
BadRequestException | 400 |
UnauthorizedException | 401 |
ForbiddenException | 403 |
NotFoundException | 404 |
ConflictException | 409 |
For a custom status, throw HttpException(message, status). For custom formatting across the app, write an exception filter.
Example
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
@Injectable()
export class UsersService {
private users = new Map<number, string>();
find(id: number) {
if (!this.users.has(id)) {
throw new NotFoundException(`User ${id} not found`);
}
return this.users.get(id);
}
}When to use it
- A developer throws NotFoundException in a service when a database record is missing so NestJS automatically returns a 404 JSON response.
- A team creates a domain exception class that extends HttpException to include a machine-readable error code alongside the HTTP status.
- An engineer uses a global exception filter to catch unknown errors and return a sanitized 500 response without leaking stack traces to clients.
More examples
Built-in HTTP exceptions
Uses the built-in NotFoundException to return a 404 with a readable message when a record does not exist.
import {
NotFoundException,
BadRequestException,
UnauthorizedException,
ForbiddenException,
ConflictException,
} from '@nestjs/common';
// In a service:
async findUser(id: number) {
const user = await this.repo.findOneBy({ id });
if (!user) throw new NotFoundException(`User ${id} not found`);
return user;
}Custom HTTP exception
Extends HttpException to create a domain-specific exception with a machine-readable code and the 429 status code.
import { HttpException, HttpStatus } from '@nestjs/common';
export class QuotaExceededException extends HttpException {
constructor(limit: number) {
super(
{ message: 'API quota exceeded', limit, code: 'QUOTA_EXCEEDED' },
HttpStatus.TOO_MANY_REQUESTS,
);
}
}
// Usage:
if (usage > limit) throw new QuotaExceededException(limit);Catch-all exception filter
A @Catch() filter with no argument catches every exception, ensuring unknown errors return a safe 500 without leaking details.
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const res = host.switchToHttp().getResponse();
const status = exception instanceof HttpException
? exception.getStatus()
: 500;
res.status(status).json({
statusCode: status,
message: status === 500 ? 'Internal server error' : (exception as any).message,
});
}
}
Discussion