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
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.
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:
or use
@UseFilter(exceptionFilter)
in your controller to handle exceptions thrown by services, and register it at the controllerwith