You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中@UserId装饰器获取ID返回NaN错误求助

问题排查:接口调用返回NaN导致数据库报错

报错信息

15556 - 29.09.2023, 20:19:14 ERROR [ExceptionsHandler] invalid input syntax for type integer: "NaN"

问题现象

  • 未添加@ApiBearerAuth()时,调用GET /profile接口仅返回第一个用户的信息;
  • 添加@ApiBearerAuth()后,触发上述报错,控制台打印的id值为NaN。

相关代码

参数装饰器(TypeScript)

export const UserId = createParamDecorator(
    (data: unknown, ctx: ExecutionContext) => {
        const request = ctx.switchToHttp().getRequest();
        return request.user?.id ? Number(request.user.id) : null;
    },
);

控制器代码

@Controller('users')
@ApiTags('users')
@ApiBearerAuth()
export class UsersController {
    constructor(private readonly usersService: UsersService) {}
    
    @Get('/profile')
    @UseGuards(JwtAuthGuard)
    getProfile(@UserId() id: number) {
      console.log(id)
      return this.usersService.findById(id);
    }
}

Service方法

async findById(id: number) {
    return this.repository.findOneBy({
     id,
    });
}

原因分析

  1. 装饰器类型转换逻辑缺陷
    装饰器中request.user?.id ? Number(request.user.id) : null的判断存在问题:

    • 若request.user.id是0、空字符串这类假值,会直接返回null;
    • 若request.user.id本身是无法转换为数字的内容(比如非数字字符串、undefined),Number()会返回NaN,最终传入Service层导致数据库报错。
  2. JWT解析后用户ID格式异常
    添加@ApiBearerAuth()后,请求会携带token并经过JwtAuthGuard验证,若JWT payload中的id不是有效数字类型(比如是字符串、或者解析后为undefined),就会导致Number()转换失败生成NaN。

  3. 未授权时的查询逻辑异常
    未添加@ApiBearerAuth()时,JwtAuthGuard可能未生效(比如Swagger未携带token,请求直接绕过验证),此时request.user不存在,装饰器返回null。数据库执行findOneBy({id: null})时,部分数据库会将null视为忽略该条件,返回第一条数据,这就是为什么只能看到第一个用户的信息。

解决方案

  1. 修正装饰器的类型转换逻辑
    先判断用户ID是否存在,再验证转换后的数字有效性:

    export const UserId = createParamDecorator(
        (data: unknown, ctx: ExecutionContext) => {
            const request = ctx.switchToHttp().getRequest();
            const userId = request.user?.id;
            if (userId == null) return null;
            const numId = Number(userId);
            // 转换失败返回null或直接抛出错误
            return isNaN(numId) ? null : numId;
        },
    );
    
  2. 校验JWT解析结果
    检查JwtAuthGuard的逻辑,确保解析token后request.user.id是有效的数字类型(比如在生成JWT时,将id存为数字而非字符串)。

  3. 添加参数校验
    在控制器或Service层增加参数校验,避免无效值传入数据库:

    getProfile(@UserId() id: number) {
      if (isNaN(id)) {
        throw new BadRequestException('无效的用户ID');
      }
      console.log(id)
      return this.usersService.findById(id);
    }
    
  4. 确保接口授权校验生效
    确认JwtAuthGuard在未携带有效token时会拦截请求,避免未授权访问导致的异常查询。


内容的提问来源于stack exchange,提问作者Максим Дмитриевич

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:48:23