NestJS is a progressive, Node.js framework for building efficient and scalable server-side applications. One of the key advantages of NestJS is its powerful dependency injection system and modular structure, which makes building enterprise-level applications more manageable.
In this article, we will explore how error handling works in NestJS and common strategies for managing exceptions
Understanding Error Handling in NestJS
Error handling in NestJS revolves around exceptions. In NestJS, errors are treated as exceptions, and the framework has a built-in exception-handling system to deal with these errors. When an error occurs, it is either thrown or caught within the system, and NestJS provides mechanisms to customize the way these exceptions are handled.
NestJS has a default error-handling mechanism that catches unhandled exceptions and sends appropriate responses, but it also allows developers to extend and customize the handling process based on the specific needs of the application.
Setting Up NestJS Application For Error Handling
Step 1: Ensure you have Node.js and npm installed
You can download and install from the site of the node.js
node --version
npm --version
Step 2: Install NestJS CLI
If you haven't already, install the NestJS CLI globally using npm:
npm install -g @nestjs/cliStep 3: Create a new NestJS Project
If you don't have a project yet, create one using the CLI and add the project file to the terminal.
nest new my-nest-project
cd my-nest-project
Step 4: Run the application
Use the following command to start your NestJS application.
npm run startFolder Structure

Dependencies
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
}
Various Approaches for Error Handling in NestJS
Table of Content
Approach 1: Built-in Exception Filters
NestJS gives integrated exception filters, like HttpException, which can help you throw commonplace HTTP errors consisting of 404, 400, 500, and etc.
Syntax:
throw new HttpException('Error Message', HttpStatus.BAD_REQUEST);Example:
//my-nest-project\src\example.controller.ts
import { Controller, Get, HttpException, HttpStatus } from '@nestjs/common';
@Controller('example')
export class ExampleController {
@Get()
getExample() {
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
}
//.\my-nest-project\src\app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ExampleController } from './example.controller';
@Module({
imports: [],
controllers: [AppController, ExampleController],
providers: [AppService],
})
export class AppModule { }
Output:

Approach 2: Custom Exception Filters
Custom exception filters assist you to manage exceptions in a custom way via extending the ExceptionFilter class and implementing the seize approach.
Example:
//.\nest2\src\cats\custom-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class CustomExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
const message = exception.message;
response
.status(status)
.json({
statusCode: status,
message: message,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
//.\nest2\src\cats\cats.controller.ts
import { Controller, Get, HttpException, HttpStatus, UseFilters } from '@nestjs/common';
import { CustomExceptionFilter } from './custom-exception.filter';
@Controller('cats')
@UseFilters(CustomExceptionFilter)
export class CatsController {
@Get()
findAll() {
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
}
Output

Approach 3: Global Exception Filters
Global exception filters may be used to deal with exceptions throughout the entire software. You can installation a global exception filter by using the usage of the app.UseGlobalFilters() method.
Example:
// custom-exception.filter.ts
import { HttpException, ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
@Catch(HttpException)
export class GlobalExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
message: exception.message,
timestamp: new Date().toISOString(),
});
}
}
//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { GlobalExceptionFilter } from './global-exception.filter';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new GlobalExceptionFilter());
await app.listen(3000);
}
bootstrap();
Output:

Approach 4: HttpException
HttpException is a integrated magnificence in NestJS for throwing HTTP-related errors.
Syntax:
throw new HttpException('Custom error message', HttpStatus.FORBIDDEN);Example:
//.\src\example\example.controller.ts
import { Controller, Get, HttpException, HttpStatus } from '@nestjs/common';
@Controller('example')
export class ExampleController {
@Get()
findAll() {
throw new HttpException(
{
statusCode: HttpStatus.FORBIDDEN,
message: 'Forbidden resource',
},
HttpStatus.FORBIDDEN,
);
}
}
Output:
{
"statusCode": 403,
"message": "Forbidden resource"
}
Approach 5: Using Middleware for Error Handling
Middleware in NestJS also can be used for errors handling with the aid of catching exceptions and modifying the reaction.
Example:
//.\src\example.controller.ts
import { Controller, Get, HttpException, HttpStatus } from '@nestjs/common';
@Controller('example')
export class ExampleController {
@Get()
findAll() {
throw new HttpException(
{
statusCode: HttpStatus.FORBIDDEN,
message: 'Forbidden resource',
},
HttpStatus.FORBIDDEN,
);
}
}
//.\src\app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ExampleController } from './example.controller';
import { ErrorHandlingMiddleware } from './error-handling.middleware';
@Module({
imports: [],
controllers: [AppController, ExampleController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(ErrorHandlingMiddleware)
.forRoutes('*');
}
}
Output

Approach 6: Using Interceptors
Interceptors can trap mistakes and alter responses earlier than they may be despatched to the patron.
Example:
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ErrorInterceptor } from './error.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new ErrorInterceptor());
await app.listen(3000);
}
bootstrap();
//error.interseptor.ts
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class ErrorInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
catchError((error) => {
if (error instanceof HttpException) {
return throwError(() =>
new HttpException({ message: 'Error intercepted' }, error.getStatus()));
}
return throwError(() =>
new HttpException({ message: 'Error intercepted' }, 500));
}),
);
}
}
Output:
