nestjs/nest · error · BadRequestException
Validation failed
Error message
Validation failed
What it means
A hand-rolled ParseIntPipe (sample/36-hmr-esm/src/common/pipes/parse-int.pipe.ts) that calls parseInt(value, 10) on an inbound route argument and throws BadRequestException('Validation failed') when the result is NaN. It is a minimal reimplementation of @nestjs/common's built-in ParseIntPipe, here to demonstrate the HMR/ESM sample's custom pipe plumbing. NaN happens when parseInt cannot find any leading digits (empty string, letters, symbols).
Source
Thrown at sample/36-hmr-esm/src/common/pipes/parse-int.pipe.ts:13
import {
ArgumentMetadata,
BadRequestException,
Injectable,
PipeTransform,
} from '@nestjs/common';
@Injectable()
export class ParseIntPipe implements PipeTransform<string> {
async transform(value: string, metadata: ArgumentMetadata) {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
View on GitHub (pinned to 6ec0e2783d)
Solutions
- Send a valid integer in the parameter (fix the client URL/query).
- Prefer NestJS's built-in ParseIntPipe, which produces a clearer message, unless the sample specifically needs a custom one.
- Tighten the check to reject non-integer strings like '12px' that parseInt silently accepts: compare String(val) !== value.
- Return a more descriptive message instead of the bare 'Validation failed'.
Example fix
// before
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
// after
const val = Number(value);
if (!Number.isInteger(val)) {
throw new BadRequestException(`Validation failed: "${value}" is not an integer`);
} Defensive patterns
Strategy: validation
Validate before calling
// Client-side: only emit numeric segments.
function toIntParam(v: string | undefined): number {
if (v == null || !/^-?\d+$/.test(v)) {
throw new Error(`"${v}" is not an integer`);
}
return Number(v);
} Type guard
function isIntegerString(v: unknown): v is string {
return typeof v === 'string' && /^-?\d+$/.test(v);
} Try / catch
// In an exception filter or controller layer
try {
const id = parseIntPipe.transform(req.params.id, { type: 'param' });
} catch (e) {
if (e instanceof BadRequestException) {
return reply.code(400).send({ message: 'id must be an integer' });
}
throw e;
} Prevention
- Prefer NestJS's built-in ParseIntPipe for clearer messages unless you need a custom one.
- Tighten the check: reject '12px' by comparing String(val) === value.
- Document which route params are numeric so clients send the right shape.
- Return the offending value in the error message for faster debugging.
When it happens
Trigger: A request whose piped parameter is not a valid integer: e.g., GET /items/abc where 'abc' flows through ParseIntPipe, or ?page= (empty). parseInt('abc',10) and parseInt('',10) both yield NaN → 400.
Common situations: Route registered without the pipe so a non-numeric segment reaches the handler; legacy/SEO URLs with slug-style ids hitting a numeric route; empty query params not stripped; client sending floating or padded strings the pipe rejects.
Related errors
- Validation failed
- 3
- Unauthorized
- The "connect()" method is not supported in gRPC mode.
- Method is not supported in gRPC mode. Use ClientGrpc instead
AI-assisted analysis of nestjs/nest@6ec0e2783d (2026-08-03).
Data as JSON: /data/errors/0933f1f5a9cad040.json.
Report an issue: GitHub.