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

如何让NestJS全局异常过滤器捕获拦截器抛出的异常?

结论

可以,按照官方文档示例配置的全局异常过滤器,完全可以正常捕获拦截器抛出的所有异常,包括拦截器内部捕获原始异常后重新抛出的其他类型异常。

原理说明

NestJS 的请求处理遵循固定的分层执行链路,所有未被中途吞掉的异常都会沿着执行链路反向冒泡,最终被注册在最外层的全局异常过滤器捕获,链路顺序从外到内依次是:

  • 全局中间件
  • 全局守卫
  • 全局拦截器(请求预处理阶段)
  • 控制器级守卫、拦截器、管道
  • 路由处理逻辑(服务、数据库操作等业务代码)
  • 全局/控制器级拦截器(响应后处理阶段)
  • 全局异常过滤器

注意:拦截器的逻辑分两个执行段,请求到达控制器前的预处理段、控制器返回结果后的响应处理段,两个阶段抛出的异常都会走统一的异常冒泡流程,不会跳过全局异常过滤器。

场景验证

举个最常见的拦截器转抛异常的例子:

@Injectable()
export class ErrorTransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler) {
    return next.handle().pipe(
      catchError((originErr) => {
        // 捕获下游抛出的原始错误,转换为自定义异常后重新抛出
        throw new CustomBizException({
          code: originErr.status || 500,
          message: `拦截器处理异常: ${originErr.message}`
        })
      })
    )
  }
}

上述代码里拦截器重新抛出的CustomBizException,会和控制器、服务层直接抛出的异常一样,被全局异常过滤器正常识别、匹配、处理,没有任何差异。

捕获失败的常见原因

如果遇到全局过滤器没抓到拦截器异常的情况,基本都是以下两个问题导致的:

  • 拦截器内部吞掉了异常:比如catchError回调里直接返回了固定默认值,没有抛出错误也没有返回throwError,异常终止传播自然到不了过滤器
  • 过滤器注册作用域错误:通过app.useGlobalFilters()在bootstrap阶段注册的过滤器是真正的应用全局级,一定能捕获;如果是通过模块内APP_FILTER令牌注册的过滤器,只有注册在根模块时才是全局作用域,注册在子模块的话作用域仅覆盖子模块内的路由,会出现捕获不到的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:03:27