skip to Main Content

I have created the exception filter and registered it globally but when I throw a HTTP exception from the service file the exception filter does not catch the exception but while throwing the exception from the controller exception filter catches the exception properly.

The exception filter:

import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
} from '@nestjs/common';
import { Response } from 'express';

@Catch(HttpException)
export class CommonFilter<T extends HttpException> implements ExceptionFilter {
  catch(exception: T, host: ArgumentsHost) {
    console.log('getting in common filter');
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
    });
  }
}

Registered as global:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { CommonFilter } from './common/common.filter';
import {
  MongooseExeptions,
  MongooseValidationError,
} from './common/mongoose.filter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: true,
      transform: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
    }),
  );
  app.useGlobalFilters(
    new CommonFilter(),
    new MongooseExeptions(),
    new MongooseValidationError(),
  );

  await app.listen(3000);
}
bootstrap();

The service function:

try {
  const pwdHash = hash(createUserDto.password, 5);
  const storeUser = await this.usersSchema.create({
    ...createUserDto,
    password: pwdHash,
  });
  if (storeUser) {
    const genrateOtp = new OTPGenrator().genrate(4);
    await this.UserOtpMailer.UserOtpMailer(
      storeUser.email,
      storeUser.name,
      genrateOtp,
    );
    return storeUser;
  }
  return;
} catch (error) {
  if (error instanceof Error.ValidationError) {
    throw new HttpException(
      error.message,
      HttpStatus.INTERNAL_SERVER_ERROR,
    );
  } else {
    throw new HttpException(
      error.message,
      HttpStatus.INTERNAL_SERVER_ERROR,
    );
  }
}

This service will throw the mongoose validation error as pwdHash is not type of string and I am throwing HTTP exception if it is validation error.

But if I throw the same error form the controller it will work fine but from service exceptions are not getting caught.

2

Answers


  1. Chosen as BEST ANSWER

    I had a mistake in my code and because of that controller was not able to catch the exception. I just needed to put await from the controller to service function.

    So we don't need to make any special setup for the nest to catch exception from the service file.


  2. The exception filter will only catch errors if they are thrown within the context of a request handled by a controller. This is because the exception filter is registered at the application level.

    in controller do this:

    async functionName() {
       try{
          ...
       } catch (error) {
          throw error;
       }
    }
    

    or use @UseFilter(exceptionFilter) in your controller to handle exceptions thrown by services, and register it at the controller

    @Controller()
    @UseFilters(MyExceptionFilter)
    export class MyController {
       ...
    }
    

    with

    @Injectable()
    export class MyExceptionFilter implements ExceptionFilter {
      catch(exception: any, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const response = ctx.getResponse();
    
        if (exception instanceof HttpException) {
          response.status(exception.getStatus()).json({
            statusCode: exception.getStatus(),
            message: exception.message,
          });
        } else {
          response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
            statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
            message: 'Internal server error',
          });
        }
      }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search