Class-validator: ValidateNested throw 500, when it receives string or number instead of object

Created on 17 Apr 2018  路  9Comments  路  Source: typestack/class-validator

I have problem with ValidationNested and I hope that someone will know how handle with it.

Have you tried to send a request with a string or number in the place where the object should be (which is validated by a @ValidateNested annotation)? It will throw error with status code 500.

Example:

export class ClassA {
    @ValidateNested()
    @Type(() => ClassB) //annotation from class-transformer
    public company: ClassB;

    @IsOptional()
    @IsInt()
    public id?: number;
}

export class ClassB {
    @IsInt()
    public id: number;

    @IsString()
    @Length(1, 255) //class-validator will try count length of this string, no matter what :(
    public name: string;
}

POST request with body:

{
    company: 5,
    id: 3
}

response:

{
    "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "TypeError: Cannot read property 'length' of undefined\n ... } //class-validator has tried count ClassB.name length

I'm using class-validator 0.8.5, class-transformer 0.1.9 and routing-controllers 0.7.6

high fix

Most helpful comment

Hi there.

Having a similar issue. It appears the validator is not picking up when the type is completely wrong, like where a string is in the place of an object. It will however correctly validate an object with incorrect fields.
I have the following setup:

export class PostInput {
  @ValidateNested()
  @Type(() => PostInputMessage)
  @IsArray()
  entries: PostInputMessage[];
}

export class PostInputMessage {
  @IsString()
  message: string;
}

if my message input contains this:

{
       "entries":["Hello", "How are you"]
}

No validation error is thrown. However if my input looks like this:

{
      "entries":[{"pinapples":"Hello"}, {"pinapples":"How are you"}]
}

A validation error is correctly thrown.
Versions: class-transformer 0.1.9, class-validator 0.8.1

All 9 comments

@konradni could you create a PR with a failing test? I see a test that should cover you case and it passes https://github.com/typestack/class-validator/blob/master/test/functional/nested-validation.spec.ts#L105

Hi @konradni!

This seems to be a bug in routing-controllers or class-transformer.

Running this code generates the correct error for me:

import { ValidateNested, IsInt, IsOptional, IsString, Length, validate } from 'class-validator';

export class ClassB {
    @IsInt()
    public id: number;

    @IsString()
    @Length(1, 255) //class-validator will try count length of this string, no matter what :(
    public name: string;
}

export class ClassA {
    @ValidateNested()
    // @Type(() => ClassB) //annotation from class-transformer
    public company: ClassB;

    @IsOptional()
    @IsInt()
    public id?: number;
}

const a = new ClassA();

a.company = <any>5;
a.id = 3;


validate(a).then(console.log);

It will return with the following (correct) error message in the right place within the error object:

nested property company must be either object or array

Hi there.

Having a similar issue. It appears the validator is not picking up when the type is completely wrong, like where a string is in the place of an object. It will however correctly validate an object with incorrect fields.
I have the following setup:

export class PostInput {
  @ValidateNested()
  @Type(() => PostInputMessage)
  @IsArray()
  entries: PostInputMessage[];
}

export class PostInputMessage {
  @IsString()
  message: string;
}

if my message input contains this:

{
       "entries":["Hello", "How are you"]
}

No validation error is thrown. However if my input looks like this:

{
      "entries":[{"pinapples":"Hello"}, {"pinapples":"How are you"}]
}

A validation error is correctly thrown.
Versions: class-transformer 0.1.9, class-validator 0.8.1

My mistake, the reason for the error from my first message was the bug in our application.
However, examples below doesn鈥檛 work correctly.

import { ValidateNested, IsInt, validate } from 'class-validator';

class ClassB {
    @IsInt()
    public id: number;
}
class ClassA {
    @ValidateNested()
    public company: ClassB;
}

const a = new ClassA();
a.company = <any>[];
validate(a).then(console.log); // returns (no errors): []

const a2 = new ClassA();
a2.company = <any>{};
validate(a2).then(console.log); // returns: []

const a3 = new ClassA();
a3.company = <any>{b: 'c'};
validate(a3).then(console.log); // returns: []

const a4 = new ClassA();
a4.company = <any>[5];
validate(a4).then(console.log); // returns: []

const a5 = new ClassA();
a5.company = <any>['b'];
validate(a5).then(console.log); // returns: []

Apologies for my first comment which was terribly written... please read again, I updated it.

@keenondrums I think that its working when you dont have the @Type decorator. As soon as u put it there, you can happily put a string in place of an object and class-validator wont throw the validation error like it should.

@konradni in your above post, no errors are thrown in each case because you are not specifying the @Type decorator, meaning that the class-validator cannot perform type specific validation on your sub object.

We need @Type to not break the default behaviour of @ValidateNested

@chrisjpalmer The addition of a @Type decorator (from class-transformer) has not changed anything :(. Besides, if I understand correctly, the @Type decorator is not necessary when I create an object using "new ClassName();" (Please correct me if I'm wrong).

@Type decorator is a type hint for reflection system, that has problem with generics like string[] is reflected as Array.

You are right @konandri u shouldn't need the @type decorator IF you are using new keyword. I am confused why class validation does not work at all in the example you provided. I find that it does work for me. I am just having the other issue of generic javascript types not being declared as invalid

@chrisjpalmer

Having a similar issue. It appears the validator is not picking up when the type is completely wrong, like where a string is in the place of an object. It will however correctly validate an object with incorrect fields.

I came across the same problem on Stackoverflow and proposed a custom validator as a workaround.

Was this page helpful?
0 / 5 - 0 ratings