【构建兼容性问题】pnpm 11 下执行 build 失败,npm_execpath 被错误地作为 Node 脚本执行 #3581
问题描述在使用 pnpm 11.7.0 和 Node.js 24.19.0 从源码构建 deepseek-harness 时,执行: pnpm install
pnpm run build构建失败。 环境:
错误信息: 问题原因分析问题应该出现在:
中的代码: const packageManager = process.env.npm_execpath
const result = spawnSync(process.execPath, [packageManager, 'run', script], {这里假设 但是在 pnpm 11 中: 可能指向: 这个文件是 Linux ELF 可执行文件,而不是 JavaScript 文件。 当前代码实际执行: node /path/to/pnpm run build:lib于是 Node.js 会尝试解析 pnpm 二进制文件: 最终导致: 补充说明这个问题在旧版本 npm/pnpm 布局下可能不会出现,因为:
但是 pnpm 11 使用了 建议后续避免依赖 |
Replies: 5 comments
|
使用windows也同样具有此问题 > pnpm run build
$ tsx scripts/build.ts
node:internal/modules/esm/get_format:243
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath);
^
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".exe" for D:\pnpm\store\v11\links\@pnpm\exe\11.7.0\a254132c028a4f0368fb9ee996a0169a530281496d7f26c4b2de752a7553ec1c\node_modules\@pnpm\exe\pnpm.exe
at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:243:9)
at defaultGetFormat (node:internal/modules/esm/get_format:283:36)
at defaultLoadSync (node:internal/modules/esm/load:161:16)
at #loadAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:802:12)
at #loadSync (node:internal/modules/esm/loader:834:53)
at ModuleLoader.load (node:internal/modules/esm/loader:783:26)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:494:31)
at #getOrCreateModuleJobAfterResolve (node:internal/modules/esm/loader:560:36)
at afterResolve (node:internal/modules/esm/loader:607:52)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:613:12) {
code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
Node.js v24.19.0
D:\Desktop\Code\github\deepseek-harness\scripts\build.ts:28
throw new Error(`build: ${script} exited with ${String(result.status ?? result.signal)}`)
^
Error: build: build:lib exited with 1
at runScript (D:\Desktop\Code\github\deepseek-harness\scripts\build.ts:28:11)
at main (D:\Desktop\Code\github\deepseek-harness\scripts\build.ts:47:3)
at <anonymous> (D:\Desktop\Code\github\deepseek-harness\scripts\build.ts:55:23)
at ModuleJob.run (node:internal/modules/esm/module_job:439:25)
at async node:internal/modules/esm/loader:643:26
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)
Node.js v24.19.0
[ELIFECYCLE] Command failed with exit code 1. |
|
MacOS 也有同样问题 正常。 |
|
linjiacheng 的直改已验证有效(Mac arm64 + Windows .cmd 均过),补一个家族视角 + 一个平台坑,让修复一次到位: 1. 这是家族级问题,不止 build.ts 一处
pnpm 11 的 2. 直改 pnpm 11 在 Windows 的 // .js → 用 process.execPath 跑(npm 传统形态);无扩展名/ELF/.exe/.cmd → 直接 spawn
const isJs = /\.c?js$/i.test(packageManager)
const result = spawnSync(isJs ? process.execPath : packageManager,
isJs ? [packageManager, 'run', script] : ['run', script], ...)这样 npm(.js)与 pnpm 11(ELF/.exe)两条路都通。 3. 建议收敛为共享 helper 5 处重复同样的 给官方:pnpm 11 已进 engines 支持范围(pnpm@11.7.0 在 #3510/#3583 里都是用户实测版本),这个 npm_execpath 假设的失效是跨 5 个脚本的 CI 兼容性债,值得一次共享修复 + 每入口回归。 |
|
补充一下对 从该文件的提交历史来看,
其中 66a7081 的变更说明中明确提到:
因此,当前触发问题的这段逻辑并不是从旧版 const packageManager = process.env.npm_execpath
const result = spawnSync(process.execPath, [packageManager, 'run', script], {
cwd: resolve(import.meta.dirname, '..'),
env: environment,
stdio: 'inherit',
})所以从目前的提交历史来看,这个兼容性问题应该可以比较明确地追溯到 66a7081 中重新引入的 建议可以考虑直接执行 spawnSync(packageManager, ['run', script], {
cwd: resolve(import.meta.dirname, '..'),
env: environment,
stdio: 'inherit',
}) |
|
已修复:scripts/build.ts 不再假设 npm_execpath 一定是 JS 入口——runScript 现在 获取修复:更新到最新 master 后,pnpm 11(@pnpm/exe 的 ELF/.exe 入口)下 |
已修复:scripts/build.ts 不再假设 npm_execpath 一定是 JS 入口——runScript 现在
经共享 helper pnpmInvocation() 构造正确的命令与参数
(scripts/build.ts:15、18-20;scripts/pnpm-invocation.ts),修复提交
89674ed(2026-08-21,"fix(build): support standalone pnpm entrypoints"),
已在当前 master(c291e7961a)上核实。
获取修复:更新到最新 master 后,pnpm 11(@pnpm/exe 的 ELF/.exe 入口)下
pnpm run build 正常,不再报 SyntaxError / ERR_UNKNOWN_FILE_EXTENSION。