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

Nest.js属性注入报错:Cannot read properties of undefined问题排查

Nest.js自定义异常类属性注入失败的原因及解决办法

核心错误原因

你遇到的Cannot read properties of undefined (reading 'getEnv')问题,本质是自定义异常类的实例不在Nest的依赖注入(DI)容器管理范围内,导致configurationHelper未被注入,具体分这几种情况:

1. 自定义异常类未标记为可注入

如果CustomException没有添加@Injectable()装饰器,Nest不会将其纳入DI容器,自然无法自动注入依赖属性。

2. 手动实例化异常类

直接使用throw new CustomException()创建的异常实例,是由你手动初始化的,不属于Nest DI容器管理的对象,Nest不会为这个实例执行依赖注入操作。

3. 模块未注册异常类为提供者

即使加了@Injectable(),如果没有在对应模块的providers数组中注册CustomException和ConfigurationHelper,DI容器也无法找到并注入依赖。

4. 混淆了自定义异常与异常过滤器的职责

自定义异常类本身通常只负责定义异常的基本信息(如消息、状态码),依赖注入的逻辑更适合放在异常过滤器中实现,而非直接在异常类里注入依赖。


解决办法

根据你的需求,提供两种可行方案:

方案1:让自定义异常类纳入DI容器管理

步骤1:标记异常类为可注入并注册模块

// custom.exception.ts
import { Injectable, Inject } from '@nestjs/common';
import { ConfigurationHelper } from './configuration.helper';

@Injectable()
export class CustomException extends Error {
  @Inject()
  private configurationHelper: ConfigurationHelper;

  constructor(message: string) {
    super(message);
    this.name = 'CustomException';
  }

  // 示例:使用注入的依赖
  getEnvValue(key: string) {
    return this.configurationHelper.getEnv(key);
  }
}
// app.module.ts
import { Module } from '@nestjs/common';
import { CustomException } from './custom.exception';
import { ConfigurationHelper } from './configuration.helper';

@Module({
  providers: [CustomException, ConfigurationHelper],
})
export class AppModule {}

步骤2:通过DI获取异常实例再抛出

不要手动new异常,而是在控制器/服务中注入CustomException实例后抛出:

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { CustomException } from './custom.exception';

@Controller()
export class AppController {
  constructor(private readonly customException: CustomException) {}

  @Get()
  getHello() {
    this.customException.message = '自定义异常消息';
    throw this.customException;
  }
}

方案2:使用异常过滤器处理依赖(更推荐)

这种方案更符合Nest的设计思想,将依赖注入逻辑放在异常过滤器中,自定义异常类仅负责定义异常结构:

步骤1:定义基础自定义异常类

// custom.exception.ts
export class CustomException extends Error {
  constructor(public message: string, public statusCode: number = 400) {
    super(message);
    this.name = 'CustomException';
  }
}

步骤2:创建带依赖注入的异常过滤器

// custom-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpStatus } from '@nestjs/common';
import { CustomException } from './custom.exception';
import { ConfigurationHelper } from './configuration.helper';

@Catch(CustomException)
@Injectable()
export class CustomExceptionFilter implements ExceptionFilter {
  constructor(private readonly configurationHelper: ConfigurationHelper) {}

  catch(exception: CustomException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    
    // 使用注入的configurationHelper获取环境变量
    const envValue = this.configurationHelper.getEnv('APP_ENV');

    response.status(exception.statusCode || HttpStatus.BAD_REQUEST).json({
      message: exception.message,
      env: envValue,
      timestamp: new Date().toISOString(),
    });
  }
}

步骤3:注册过滤器

可以在控制器上局部注册,或者全局注册:

// app.controller.ts
import { Controller, Get, UseFilters } from '@nestjs/common';
import { CustomException } from './custom.exception';
import { CustomExceptionFilter } from './custom-exception.filter';

@Controller()
@UseFilters(CustomExceptionFilter)
export class AppController {
  @Get()
  getHello() {
    throw new CustomException('出错了');
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 17:37:12