症状
错误“Node ERR_PACKAGE_PATH_NOT_EXPORTED — 子路径被 exports 映射封锁”指向一个明确的失效模式。下面依次给出症状、定位该原因的检查命令、根本原因、修复方案,以及证明修复有效的验证步骤。
可观察到的症状包括:
- Node 抛出 “ERR_PACKAGE_PATH_NOT_EXPORTED: Package subpath … is not defined by exports”
- 同一条 import 在依赖升级小版本后突然失效
- 打包器能解析该路径,而原生 Node 拒绝
诊断
先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。
步骤 1
node -e "console.log(JSON.stringify(require('./node_modules/<pkg>/package.json').exports, null, 2))"
该映射精确列出可导入的子路径;若你的路径不在其中,说明该导入被有意设为私有。
步骤 2
node --input-type=module -e "import('<pkg>/dist/foo.js')"
此处直接报解析错误,可确认是 exports 限制而非依赖未安装。
步骤 3
node -e "const e=require('./node_modules/<pkg>/package.json').exports; console.log(Object.keys(e))"
选择一个已声明的入口,如包根或文档化的功能路径。
常见诱因(按出现频率排序):
- 依赖新增 exports 映射,列出允许的子路径,却未包含你导入的那个
- 你导入了内部文件路径(如 pkg/dist/foo.js),而非文档化的子路径
- 条件字段(import/require/default)未覆盖你使用的解析模式
根因
一旦 package.json 存在 exports 字段,Node 会把其中未列出的所有子路径视为私有,即使文件确实存在于磁盘。导入内部文件路径因此触发 ERR_PACKAGE_PATH_NOT_EXPORTED。
修复
只导入 exports 映射声明的子路径,或升级到暴露所需能力的版本。若该包由你维护,应在正确的条件下把子路径加入 exports,而不是访问 dist。
注意:在没有 “./*” 兜底的情况下加入 exports 对使用深层路径的调用方是破坏性变更,需按破坏性版本处理。
// package.json of the dependency
{
"exports": {
".": { "import": "./dist/index.mjs", "require": "./dist/index.cjs" },
"./parser": "./dist/parser.mjs"
}
}
// ✅ import a declared subpath
import { parse } from 'the-pkg/parser';
// ❌ import a private file path (throws ERR_PACKAGE_PATH_NOT_EXPORTED)
// import { parse } from 'the-pkg/dist/parser.mjs';
验证
重新执行 import 并确认无错误。补充一条导入公开入口的冒烟测试,让日后的 exports 修改在测试中暴露,而不是在生产中出问题。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。