Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NestJS throw from ExceptionFilter

I try to use an ExceptionFilter to map exceptions to their HTTP counterpart.

This is my code :

@Catch(EntityNotFoundError)
export class EntityNotFoundFilter implements ExceptionFilter {
    catch(exception: EntityNotFoundError, _host: ArgumentsHost) {
        throw new NotFoundException(exception.message);
    }
}

But, when the filter code is executed, I got a UnhandledPromiseRejectionWarning

 (node:3065) UnhandledPromiseRejectionWarning: Error: [object Object]
    at EntityNotFoundFilter.catch ([...]/errors.ts:32:15)
    at ExceptionsHandler.invokeCustomFilters ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:49:26)
     at ExceptionsHandler.next ([...]/node_modules/@nestjs/core/exceptions/exceptions-handler.js:13:18)
     at [...]/node_modules/@nestjs/core/router/router-proxy.js:12:35
     at <anonymous>
     at process._tickCallback (internal/process/next_tick.js:182:7)
 (node:3065) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5)

How can I fix this ?

like image 508
Varkal Avatar asked Mar 01 '19 13:03

Varkal


1 Answers

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.

like image 169
Kim Kern Avatar answered Nov 08 '22 11:11

Kim Kern