Description
Description
I’m experiencing an issue where my global ValidationPipe is registered but doesn’t run on requests when using the Fastify adapter in a production build (both locally and on my production server). Even though I see the registration logs, extra query parameters are neither stripped nor rejected.
Reproduction Steps:
- Setup Nest with FastifyAdapter
`// main.ts
import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { ValidationPipe, Logger } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(
AppModule,
new FastifyAdapter({ logger: true }),
);
const logger = new Logger('Bootstrap');
logger.log('FastifyAdapter registered');
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
transformOptions: { enableImplicitConversion: true },
}));
logger.log('ValidationPipe registered');
await app.listen(3000, '0.0.0.0');
logger.log('App is running');
}
bootstrap();`
- Define a simple DTO and controller
`// dto/simple.dto.ts
import { IsOptional, IsString } from 'class-validator';
export class SimpleDto {
@IsOptional()
@IsString()
tz?: string;
}
// controllers/simple.controller.ts
import { Controller, Get, Query } from '@nestjs/common';
import { SimpleDto } from '../dto/simple.dto';
@controller('simple')
export class SimpleController {
@get()
test(@query() dto: SimpleDto) {
return dto;
}
}`
-
Build & run in production mode (locally)
npm run build # uses tsconfig.build.json
NODE_ENV=production node dist/main.js -
Send request with extra query param
curl -i 'http://localhost:3000/simple?tz=Europe/Istanbul&foo=bar' -
Observe behavior
Expected: Request is rejected with 400 Bad Request due to foo being non-whitelisted.
Actual: Request succeeds (200 OK), returning both tz and foo intact.
Environment:
- NestJS: 10.x
- @nestjs/platform-fastify: 10.x
- class-validator: 0.14.x
- class-transformer: 0.5.x
- Node.js: 20.x
- tsconfig.build.json:
{ "extends": "./tsconfig.json", "compilerOptions": { "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "ES2021", "module": "CommonJS" }, "exclude": ["node_modules", "test", "dist"] }
Error Message:
`HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"message": [
{
"property": "tz",
"constraints": {
"whitelistValidation": "property tz should not exist"
}
}
],
"error": "Bad Request",
"statusCode": 400
}`
Additional Context:
- The same setup works correctly in development mode (NODE_ENV=development) and locally when running the production build (NODE_ENV=production).
- I see both FastifyAdapter registered and ValidationPipe registered in logs in all environments.
- Even with global settings whitelist: false and forbidNonWhitelisted: false, I still receive the whitelistValidation error for tz.
- Using @Allow() on specific DTO properties also does not resolve the inconsistency.
- Switching to Express adapter makes validation work as expected.
- This issue occurs regardless of environment, but only when using the Fastify adapter in a production build.
- Any guidance on fixing global pipes under Fastify in a production build would be greatly appreciated!