error.prototype.cause 是 es2022 引入的标准属性,用于显式声明错误的根本原因;需在 new error(msg, { cause }) 中手动传入,推荐始终使用 error 实例,现代环境已原生支持,微服务中应在 http 客户端拦截器统一注入,并由 apm 工具递归采集 cause 链以增强链路追踪与告警可读性。

Error.prototype.cause 是 ECMAScript 2022(ES13)正式引入的标准属性,用于显式声明一个错误的“根本原因”。在微服务架构中,当异常跨服务传播时,原始错误信息极易丢失或被覆盖。合理使用 cause 可以构建可追溯、层次清晰的异常因果链,显著提升链路追踪与问题定位效率。
明确 cause 的语义与构造方式
该属性不是自动填充的,必须在创建新 Error 实例时通过 options 对象显式传入:
- 推荐用法:
new Error('服务B调用超时', { cause: originalError }) - cause 值可以是任意值(不限于 Error 实例),但为保障工具链兼容性,建议始终传入 Error 类型
- Node.js 16.9+ 和现代浏览器(Chrome 93+、Firefox 91+、Safari 15.4+)已原生支持;旧环境需 polyfill 或降级处理
在 HTTP 客户端层统一注入 cause
微服务间通常通过 HTTP 调用通信。在封装的请求客户端(如 axios 拦截器或 fetch 包装函数)中捕获响应错误,并将上游返回的错误详情作为 cause 封装:
- 若下游返回 5xx 或结构化错误体(如
{ "error": "DB connection failed", "traceId": "xxx" }),应解析后构造新 Error 并设为 cause - 避免仅拼接 message(如
`[UserSvc] ${err.message}`),这会丢失堆栈和上下文元数据 - 示例:在 Axios 响应拦截器中:
throw new Error(`HTTP ${error.response?.status} from AuthSvc`, { cause: error });
链路追踪 SDK 需主动读取并上报 cause 链
主流 APM 工具(如 OpenTelemetry JS SDK、Datadog RUM、Sentry)默认只采集顶层 Error 的 message、stack 和 name。要让因果链进入追踪系统,需手动展开:
- 递归遍历
error.cause,收集每层的message、stack、name,合并为结构化字段(如error.cause_chain) - OpenTelemetry 中可在
span.recordException()前预处理 error,将 cause 链附加到 span attributes - Sentry 推荐用
addBreadcrumb记录各层 cause,并通过extra字段透传完整链路
日志与告警中还原因果上下文
结构化日志(如 JSON 格式)应包含完整的 cause 层级,而非只打印顶层错误:
- 使用
util.inspect(error, { depth: null, showHidden: true })(Node.js)或自定义序列化函数,确保 cause 不被忽略 - 告警消息模板中加入
{{error.cause?.message}}或类似变量,让值班人员一眼看到根因(如 “数据库连接拒绝” 而非 “服务调用失败”) - 避免在日志中做字符串拼接掩盖 cause 结构,例如不要写
console.error(`${e.message} (caused by ${e.cause?.message})`)










