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
相关产品推荐
相关产品推荐

