nest: Validation fails with latest 0.14.0 version of class-validator

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Note This is an issue opened by a class-validatior maintainer to raise awareness of the latest breaking change in the class-validator@0.14.0 version and provide guidance on how to work around it.

The latest 0.14.0 release of class-validator changed the default option for forbidUnknownValues from false to true. The old behavior can be restored by specifying forbidUnknownValues: false when providing ValidatorOptions to NestJS.

This means validation of class instances where no actual validation takes place will fail instead of silently passing. This is the expected behavior for the majority of use cases.

There are two scenarios when this can happen:

  • the metadata is not registered correctly
  • when using group validation and the specified validation group results in zero validation applied

The first case will be a misconfiguration in your project 99% of the time, and you probably never want to allow payloads to bypass validation due to missing metadata. In this case, you need to find out why no metadata is present to do validations.

The second case may be a legit use case when you want to support validation groups that are exclusive to each other. If the called validation excludes all metadata due to the specified group then the validation will fail from now on instead of passing. Example:

class MyPayload {
    @IsString({ groups: ['A']})
    property: string;

    constructor(property: string) {
      this.property = property;
    }
}

validate(new MyPayload('value'), { groups: ['B'] }).then(console.log);

Calling the above will result in an error from now on:

[
  ValidationError {
    target: MyPayload { property: 'value' },
    value: undefined,
    property: undefined,
    children: [],
    constraints: {
      unknownValue: 'an unknown value was passed to the validate function'
    }
  }
]

If this is your use case you need to restore forbidUnknownValues: false or re-think your approach to how you are using groups.

For more details see PR #1798 and #1422 (comment).

Minimum reproduction code

https://github.com/typestack/class-validator/blob/develop/CHANGELOG.md#0140-2022-12-09

Steps to reproduce

  1. update class-validator to the latest 0.14.0 version
  2. use group validation or incorrectly configure your decorator metadata
  3. observe the failing validations which were passing in the previous versions

Expected behavior

The affected code is updated by the affected developers.

Package

Other package

class-validator

NestJS version

9.2.1

Packages versions


Node.js version

v18.12.1

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 16
  • Comments: 15 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Since this caused quite an important regression (described here https://github.com/nestjs/nest/issues/10683#issuecomment-1349614194) I’m going to create a PR shortly that will set forbidUnknownValues to false by default. We can think about removing this fallback in the next major release

Example:

/**
 * This post body is completely undecorated.
 */
class MyInputModel {
  foo: string;
}

@Controller('/test')
export class MyTestController {
  @Post()
  async postTest(@Body() body: MyInputModel) {
    return; // expect HTTP 201, receive HTTP 400
  }
}

Suggestions for developers running into this error:

  • Pin to class-validator < 0.14
  • Use the option {forbidUnknownValues: false}, e.g. app.useGlobalPipes(new ValidationPipe({forbidUnknownValues: false}));
  • Update models to include class-validator decorators.

The following documentation may need to be updated:

Since TypeScript does not store metadata about generics or interfaces, when you use them in your DTOs, ValidationPipe may not be able to properly validate incoming data. For this reason, consider using concrete classes in your DTOs.

@scopsy my team ran into a similar issue in our monorepo - we ended up tracking it down to what we think is an issue in class-transformer that I just opened typestack/class-transformer#1440 to address. FYI @NoNameProvided

typestack/class-transformer#1043 gives a really good description of the problem with sharing validators within a monorepo. We ended up using a very similar workaround as the people from that thread:

  1. Making class-validator and class-transformer peer dependencies in our shared libraries to remove additional installations of those packages - this fixes things for published packages
  2. Using tsconfig compiler paths to force the server to only use its local reference (same concept as this workaround but without webpack) - this fixes things for local development

@micalevisk I am not sure what reproduction case do you asking for. This is an issue opened to raise awareness of a breaking change. I myself did not run into any problems with NestJs so I have no reproduction case to provide.

I’ve having the same issue with class-validator as well, but using TypeGraphQL. There’s no options to do app.useGlobalPipes(new ValidationPipe({forbidUnknownValues: false})); like how nestjs does it, does anyone happen to know a TypeGraphQL equivalent version of this fix?

TIA

@NoNameProvided any tips on the the metadata is not registered correctly we have a monorepo (https://github.com/novuhq/novu/pull/2494) and I’ve updated typescript versions to match on relevant packages, but seems like still it’s failing in this scenario.

Any tips?

There are two scenarios when this can happen:

the metadata is not registered correctly

@NoNameProvided It would be helpful if you could provide a few examples of this case where you say metadata is not registered correctly. If I am upgrading the package, then just checking if at least some decorators are added to the classes which are being used for validation would do the job, or do I need to check for something else as well?