typescriptvalidationjwtnestjsbackend

Validation Error with Numeric String Expected in NestJS DTO


I’m working on a NestJS application and encountering a validation error when sending a request to the http://localhost:3000/users/authstatus endpoint. The error message is:

{
    "message": "Validation failed (numeric string is expected)",
    "error": "Bad Request",
    "statusCode": 400
}

Here’s a summary of my setup:

  1. DTO Class (CreatePostDto):
import { IsInt, IsNotEmpty, IsNumberString, IsOptional, IsString } from 'class-validator';

export class CreatePostDto {
  @IsNotEmpty()
  @IsString()
  title: string;

  @IsNotEmpty()
  @IsString()
  content: string;

  @IsOptional()
  @IsString()
  mainImageUrl: string;

  @IsInt()
  userId: number;

  @IsInt()
  categoryId?: number; // Optional field
}
  1. Current User Guard:
import { ExecutionContext } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";

export class CurrentUserGuard extends AuthGuard('jwt') {
  handleRequest(err: any, user: any) {
    if (user) return user;
    return null;
  }
}

  1. JWT Strategy::
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { Request } from 'express';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(@InjectRepository(User) private readonly userRepo: Repository<User>) {
    super({
      jwtFromRequest: ExtractJwt.fromExtractors([(request: Request) => {
        return request?.cookies?.Authentication;
      }]),
      ignoreExpiration: false,
      secretOrKey: 'secretKey', // Use your own secret key here
    });
  }

  async validate(payload: any, req: Request) {
    if (!payload) {
      throw new UnauthorizedException('Invalid JWT payload');
    }

    const user = await this.userRepo.findOneBy({ username: payload.username });
    if (!user) {
      throw new UnauthorizedException();
    }
    req.user = user;
    return req.user;
  }
}

  1. Current User Decorator and Endpoint:
import { ExecutionContext, createParamDecorator } from "@nestjs/common";

export const CurrentUser = createParamDecorator(
  (data: unknown, context: ExecutionContext) => {
    const request = context.switchToHttp().getRequest();
    return request.user;
  }
);

@Get('auth-status')
@UseGuards(CurrentUserGuard)
@HttpCode(HttpStatus.OK)
authStatus(@CurrentUser() user: User) {
  console.log('Authenticated User:', user);
  return { status: !!user, user };
}

I’m receiving a validation error indicating that a numeric string is expected. I’m not sure which part of the code is causing this issue or how to resolve it.

What I’ve tried:

Verified the DTO and decorator usage Checked the request payload for issues Ensured the JWT strategy is correctly configured

Any help or guidance on how to fix this validation error would be greatly appreciated! thank u !


Solution

  • Please, inspect your request and check if it is sending userId as a string.

    The Class Validator will not cast it for you, so "1" will not be let through.

    You can add transform decorator that will parse it to string:

    @Transform(({ value }) => value ? Number(value) : value)
    @IsInt()
    userId: number
    

    Note that transform needs to be placed before @IsInt()

    Hope that helps.

    P.S.: alternatively, you can use @IsNumberString() decorator instead of @IsInt()