fix: @Length with each: true on string[] reports wrong constraint in error message
Description
When using @Length(min, max, { each: true }) on a string[] property, the error message does not always reflect the constraint that was actually violated. In the example below, passing a value that is too long results in a message saying the value is too short
Steps to Reproduce
import { Length, validate } from 'class-validator';
class Dto {
@Length(3, 4, { each: true })
tags: string[];
}
const dto = new Dto();
dto.tags = ['ABCDE']; // 5 chars — longer than the max of 4
validate(dto).then(errors => {
console.log(errors[0].constraints);
});Expected behavior
{ isLength: 'each value in tags must be shorter than or equal to 4 characters' }
or at minimum the range message:
{ isLength: 'each value in tags must be longer than or equal to 3 and shorter than or equal to 4 characters' }
Actual behavior
{ isLength: 'each value in tags must be longer than or equal to 3 characters' }
Environment
class-validator: 0.15.1
Possible Root Cause (not certain)
Looking at the defaultMessage implementation in Length.ts, the message branch is selected based on args.value.length:
if (isMinLength && (!args.value || args.value.length < args?.constraints[0])) {
return eachPrefix + '$property must be longer than or equal to $constraint1 characters';
} else if (isMaxLength && args.value.length > args?.constraints[1]) {
return eachPrefix + '$property must be shorter than or equal to $constraint2 characters';
} When each: true is used, it is possible that args.value inside buildMessage refers to the array itself rather than the individual item being validated. If that is the case, args.value.length would give the array size (e.g. 1) instead of the string length (e.g. 5), which would explain why the wrong branch fires.
I haven't been able to fully trace how buildMessage is called internally when each: true is set, so I may be missing something.
Workaround
Splitting into two separate decorators avoids the issue:
@MinLength(3, { each: true })
@MaxLength(4, { each: true })
tags: string[];Have a good day
Source: typestack/class-validator