NestJS throw from ExceptionFilter
The ExceptionFilter
is always the last place that gets called before a response is sent out, it is responsible for building the response. You cannot rethrow an exception from within an ExceptionFilter
.
@Catch(EntityNotFoundError)export class EntityNotFoundFilter implements ExceptionFilter { catch(exception: EntityNotFoundError, host: ArgumentsHost) { const response = host.switchToHttp().getResponse(); response.status(404).json({ message: exception.message }); }}
Alternatively, you can create an Interceptor
that transforms your errors:
@Injectable()export class NotFoundInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { // next.handle() is an Observable of the controller's result value return next.handle() .pipe(catchError(error => { if (error instanceof EntityNotFoundError) { throw new NotFoundException(error.message); } else { throw error; } })); }}
Try it out in this codesandbox.
The key here is to extend the BaseExceptionFilter
and delegate to the super class rather than throwing:
import { BaseExceptionFilter } from '@nestjs/core';// .. your other imports@Catch(EntityNotFoundError)export class EntityNotFoundFilter extends BaseExceptionFilter { catch(exception: EntityNotFoundError, host: ArgumentsHost) { super.catch(new NotFoundException(exception.message, host)); }}
Be sure to pass in the applicationRef
argument when constructing your filter during your application bootstrapping, because the BaseExceptionFilter
needs this property to behave correctly
import { HttpAdapterHost } from '@nestjs/core';// .. your other importsasync function bootstrap(): Promise<void> { // .. blah blah const { httpAdapter } = app.get(HttpAdapterHost); app.useGlobalFilters(new GeneralErrorFilter(httpAdapter)); // .. blah blah}
This will result in the default error handling you would receive if you had thrown the same error.
Base on Kim Kern solution I've created this abstract class
export abstract class AbstractErrorInterceptor<T> implements NestInterceptor { protected interceptedType: new (...args) => T; intercept( context: ExecutionContext, call$: Observable<any>, ): Observable<any> | Promise<Observable<any>> { return call$.pipe( catchError(exception => { if (exception instanceof this.interceptedType) { this.handleError(exception); } throw exception; }), ); } abstract handleError(exception: T);}
And some implementations
export class EntityNotFoundFilter extends AbstractErrorInterceptor<EntityNotFoundError> { interceptedType = EntityNotFoundError; handleError(exception: EntityNotFoundError) { throw new NotFoundException(exception.message); }}