Exception filters

The only difference between HTTP exception filter layer and corresponding microservices layer is that instead of throwing HttpException, you should rather use RpcException.

  1. throw new RpcException('Invalid credentials.');

info Hint The RpcException class is imported from the @nestjs/microservices package.

Nest will handle thrown exception and as a result, returns the error object with the following structure:

  1. {
  2. "status": "error",
  3. "message": "Invalid credentials."
  4. }

Filters

The exception filters work in the same fashion as the primary ones, with a one, small difference. The catch() method has to return an Observable.

  1. @@filename(rpc-exception.filter)
  2. import { Catch, RpcExceptionFilter, ArgumentsHost } from '@nestjs/common';
  3. import { Observable, throwError } from 'rxjs';
  4. import { RpcException } from '@nestjs/microservices';
  5. @Catch(RpcException)
  6. export class ExceptionFilter implements RpcExceptionFilter<RpcException> {
  7. catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
  8. return throwError(exception.getError());
  9. }
  10. }
  11. @@switch
  12. import { Catch } from '@nestjs/common';
  13. import { throwError } from 'rxjs';
  14. @Catch(RpcException)
  15. export class ExceptionFilter {
  16. catch(exception, host) {
  17. return throwError(exception.getError());
  18. }
  19. }

Warning It is impossible to set up the microservice exception filters globally when the hybrid application feature is being used.

Here is an example that makes use of a manually instantiated method-scoped filter (class-scoped works too):

  1. @@filename()
  2. @UseFilters(new ExceptionFilter())
  3. @MessagePattern({ cmd: 'sum' })
  4. accumulate(data: number[]): number {
  5. return (data || []).reduce((a, b) => a + b);
  6. }
  7. @@switch
  8. @UseFilters(new ExceptionFilter())
  9. @MessagePattern({ cmd: 'sum' })
  10. accumulate(data) {
  11. return (data || []).reduce((a, b) => a + b);
  12. }

Inheritance

Typically, you’ll create fully customized exception filters crafted to fulfill your application requirements. There might be use-cases though when you would like to reuse an already implemented, core exception filter, and override the behavior based on certain factors.

In order to delegate exception processing to the base filter, you need to extend BaseExceptionFilter and call inherited catch() method. Besides, HttpServer reference has to be injected and passed to the super() call.

  1. @@filename()
  2. import { Catch, ArgumentsHost } from '@nestjs/common';
  3. import { BaseRpcExceptionFilter } from '@nestjs/microservices';
  4. @Catch()
  5. export class AllExceptionsFilter extends BaseRpcExceptionFilter {
  6. catch(exception: any, host: ArgumentsHost) {
  7. return super.catch(exception, host);
  8. }
  9. }
  10. @@switch
  11. import { Catch } from '@nestjs/common';
  12. import { BaseRpcExceptionFilter } from '@nestjs/microservices';
  13. @Catch()
  14. export class AllExceptionsFilter extends BaseRpcExceptionFilter {
  15. catch(exception, host) {
  16. return super.catch(exception, host);
  17. }
  18. }

Obviously, you should enhance above implementation with your tailored business logic (e.g. add various conditions).