Careeroza
Validation Error Response
The Default 400 Response
Example
curl -i -X POST http://localhost:3000/products -H "Content-Type: application/json" \
-d '{"name":"TV","price":-100,"stock":2.5,"category":"toys"}'Example output
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"message": [
"name must be longer than or equal to 3 characters",
"price must be a positive number",
"stock must be an integer number",
"category must be one of the following values: audio, mobiles, laptops, wearables, accessories"
],
"error": "Bad Request",
"statusCode": 400
}Custom Messages and a Custom Format
Each decorator takes a message. To change the whole response shape, pass an exceptionFactory:
import { BadRequestException, ValidationError, ValidationPipe } from '@nestjs/common';
// in a DTO
export class CreateProductDto {
@IsPositive({ message: 'Price must be more than ₹0' })
price: number;
}
// in main.ts
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
transform: true,
exceptionFactory: (errors: ValidationError[]) =>
new BadRequestException({
code: 'VALIDATION_FAILED',
fields: Object.fromEntries(errors.map((e) => [e.property, Object.values(e.constraints ?? {})])),
}),
}),
);Example
curl -X POST http://localhost:3000/products -H "Content-Type: application/json" -d '{"name":"TV","price":-100}'Example output
{"code":"VALIDATION_FAILED","fields":{"name":["name must be longer than or equal to 3 characters"],"price":["Price must be more than ₹0"],"stock":["stock must not be less than 0","stock must be an integer number"],"category":["category must be one of the following values: audio, mobiles, laptops, wearables, accessories","category should not be empty"]}}Exercise: Write a RegisterUserDto with: name (2–50 chars), email (valid email), phone (Indian mobile), password (min 8 chars, at least one digit).
Show answer
import { IsEmail, IsMobilePhone, IsString, Length, Matches, MinLength } from 'class-validator';
export class RegisterUserDto {
@IsString()
@Length(2, 50)
name: string;
@IsEmail()
email: string;
@IsMobilePhone('en-IN')
phone: string;
@IsString()
@MinLength(8)
@Matches(/\d/, { message: 'password must contain a number' })
password: string;
}