Search code examples
nestjsclass-validator

How to make class-validator to stop on error?


I want class validator to stop validation as soon as the first error is found.

I know there is a stopAtFirstError option, but that prevents further validation on property level only. I want to stop it globally:

@IsString() // Let's say this received invalid value
someStr: string

@IsInt() // I want this to be NOT executed
someNuber: number

Is this possible?


Solution

  • Since there is no official support for this, I implemented a hacky way to make it work. Although it doesn't stop the validation, only returns the message from initial one & ignores the rest.

    ValidationErrorException

    // validation-error.exception.ts
    
    import { HttpException, HttpStatus } from "@nestjs/common";
    
    export class ValidationErrorException extends HttpException {
      data: any;
      constructor(data: any) {
        super('ValidationError', HttpStatus.BAD_REQUEST);
        this.data = data
      }
      getData(){
        return this.data;
      }
    }
    

    Use Exception Factory to return the exception

    // main.ts
    
    app.useGlobalPipes(
        new ValidationPipe({
          whitelist: true,
          forbidNonWhitelisted: true,
          stopAtFirstError: true,
          exceptionFactory: (errors: ValidationError[]) => {
            return new ValidationErrorException(errors);
          },
        }),
      );
    

    Validation Error Filter

    // validation-error.filter.ts
    
    import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
    import { Response } from 'express';
    import { ValidationErrorException } from './validation-error.exception';
    
    @Catch(ValidationErrorException)
    export class ValidationErrorFilter implements ExceptionFilter {
      catch(exception: ValidationErrorException, host: ArgumentsHost) {
        const response = host.switchToHttp().getResponse<Response>();
        const status = exception.getStatus();
        let constraints = exception.getData()[0].constraints
    
        response
          .status(status)
          .json({
            statusCode: status,
            message: constraints[Object.keys(constraints)[0]],
            error: exception.message
          });
      }
    }
    

    Use The filter

    // app.module.ts
    
    providers: [
        {
          provide: APP_FILTER,
          useClass: ValidationErrorFilter,
        },
      ],