Skip to content

Instantly share code, notes, and snippets.

@josephdpurcell
Last active June 18, 2025 06:36
Show Gist options
  • Select an option

  • Save josephdpurcell/9af97c36148673de596ecaa7e5eb6a0a to your computer and use it in GitHub Desktop.

Select an option

Save josephdpurcell/9af97c36148673de596ecaa7e5eb6a0a to your computer and use it in GitHub Desktop.
NestJS: Ignore global ValidationPipe interceptor for a controller route

How does this work?

The NestJS ValidationPipe does not validate custom decorators. So, in this above example we just make a @RawBody() param decorator, and NestJS will skip validating it.

Take a look at NestJS' ValidationPipe class at the relevant points:

Here is where it checks to see if the decorator type is 'custom':

https://github.com/nestjs/nest/blob/master/packages/common/pipes/validation.pipe.ts#L164-L166

Here is where it returns if validation shouldn't apply:

https://github.com/nestjs/nest/blob/master/packages/common/pipes/validation.pipe.ts#L102-L106

Links

Here are some links that talk about this issue and some documentation links that are relevant:

import { ValidationPipe } from '@nestjs/common';
// ...
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}));
// ...
import { Body, Controller, Post } from '@nestjs/common';
import { RawBody } from './raw-body.ts';
import { MyDto } from './my.dto';
@Controller()
export class MyController {
@Post()
async post(
@RawBody() params: MyDto
): Promise<void> {
// params will be a raw un-typed object with no validation having been run on it!
}
}
import { IsNotEmpty } from "class-validator";
export class MyDto {
@IsNotEmpty()
field: string;
}
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const RawBody = createParamDecorator(
(data: unknown, ctx: ExecutionContext): any => {
const request = ctx.switchToHttp().getRequest();
return request.body;
}
);
@misaelabanto
Copy link

This was very useful, thank you! 👍

@yosletpp
Copy link

Thanks mate !

@Waer1
Copy link

Waer1 commented Jul 8, 2024

great work mate!

@talski
Copy link

talski commented Jan 31, 2025

not so nice to have to write validateCustomDecorators: true, but it works, thank you

@Tomas2D
Copy link

Tomas2D commented Feb 8, 2025

Thank you!

@leonardo-moraes360
Copy link

Really useful, but I used for the query instead.

@GHkrishna
Copy link

GHkrishna commented Jun 12, 2025

Really useful, thank you! @josephdpurcell

I ended up taking the Alternate 3 approach – creating a custom ValidationPipe and registering it globally, with logic to override validator options per DTO. This gave me precise control while preserving the global defaults. It also kept class-validator decorators active, which was important for Swagger/OpenAPI support.

Alternate 3: Custom ValidationPipe

Write your own custom ValidationPipe class, use that globally, and do some checking logic there?

I documented the entire flow and comparison here in this gist, where we can see how to dynamically override whitelist or transform only for specific DTOs, without affecting the global settings and also touched base upon difference between this two approaches.
Questions are most welcomed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment