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

NestJS集成Prisma时全局异常过滤器状态码始终为500

问题根因

Prisma 提供的findUniqueOrThrow、findFirstOrThrow等抛错方法,查询无结果时抛出的不是NestJS内置的HttpException实例,而是Prisma自身封装的NotFoundError(错误码P2025,继承自Prisma客户端基础错误类)。
当前全局异常过滤器的状态码判断逻辑仅对HttpException类型的异常做了适配,Prisma抛出的原生错误不满足该类型判断条件,因此会直接走兜底逻辑返回500状态码。另外原过滤器中catch方法的异常参数固定写为HttpException类型也存在类型定义问题,全局过滤器需要接收所有抛出的异常,类型应该定义为unknown。

修复方案

可根据项目架构选择以下任意一种方案:

方案1:全局过滤器统一适配Prisma错误

直接在全局异常过滤器中增加Prisma错误类型的判断分支,统一做状态码和错误信息映射,修改后的过滤器代码如下:

import { Catch, ExceptionFilter, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
import { Prisma } from '@prisma/client';

@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
  constructor(private readonly httpAdapterHost: HttpAdapterHost) {}

  catch(exception: unknown, host: ArgumentsHost) {
    const { httpAdapter } = this.httpAdapterHost;
    const ctx = host.switchToHttp();

    let status = HttpStatus.INTERNAL_SERVER_ERROR;
    let message = '服务内部异常';

    // 识别Nest标准HTTP异常
    if (exception instanceof HttpException) {
      status = exception.getStatus();
      const exceptionRes = exception.getResponse();
      message = typeof exceptionRes === 'string' 
        ? exceptionRes 
        : Array.isArray((exceptionRes as any).message) 
          ? (exceptionRes as any).message.join(';') 
          : (exceptionRes as any).message || exception.message;
    } 
    // 识别Prisma查询不存在错误
    else if (exception instanceof Prisma.NotFoundError) {
      status = HttpStatus.NOT_FOUND;
      message = '请求的资源不存在';
    }

    const responseBody = {
      success: false,
      message,
    };

    httpAdapter.reply(ctx.getResponse(), responseBody, status);
  }
}

方案2:业务层转换为标准HTTP异常

如果不希望全局过滤器耦合Prisma相关依赖,可以在业务逻辑层捕获Prisma抛出的错误,手动转换为Nest内置的NotFoundException(继承自HttpException),全局过滤器无需修改即可正确识别404状态码,示例代码如下:

import { Injectable, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';

// 服务层方法修改
async findOne(id: number) {
  try {
    return await this.prisma.restaurant.findUniqueOrThrow({
      where: { id },
    });
  } catch (err) {
    if (err instanceof Prisma.NotFoundError) {
      throw new NotFoundException(`ID为${id}的餐厅记录不存在`);
    }
    throw err;
  }
}

该方案耦合度更低,全局过滤器只需要处理标准HTTP异常即可,适合分层清晰的项目使用。


内容的提问来源于stack exchange,提问作者ShaSha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:48:39