support fnm nvm #648

Closed
opened 2026-10-06 15:45:12 +08:00 by k88936 · 0 comments
Member

Understood. Two things: (1) get my commit out of your tree, (2) fix the environment rather than the code. Let me check what this host's Node setup actually looks like while I revert my commit.

I'm on your machine (k88936-t14p). I can see it: your active node is fnm v22.23.3, but there's also a system /usr/bin/node. Let me pin down which one the app picked and whether the system npm is complete.

/usr/bin/node is v26.10.0 — that's the one the app used. But look at the system npm: bin/npm-cli.js is only 54 bytes and lib/cli.js is 407 bytes. Those are stubs, not real npm. Let me read them.

These are real npm 12.2.0 files, and /usr/bin/npm --version works on the host. So the sandbox is the problem. Let me read exactly how bwrap is assembled.

Let me stop theorizing and reproduce directly — I'm root on the host and can run bwrap with the same binds the app uses.

The minimal bwrap test shows /usr/bin/npm actually loads fine under --ro-bind /usr /usr (it got past ../lib/cli.js). So the app must be using a different npm. The app is running as PID 312426 — let me read its real environment.

The app (PID 312426) has this PATH, with fnm v22.23.3 first and /usr/bin later:

/root/.local/bin:/run/user/0/fnm_multishells/1117_.../bin:...:/usr/bin:...

So resolve_node_runtime picks the fnm node. The sandbox then mounts only the fnm npm shim — no fnm node, no npm lib/ — so the shim's env node falls through to /usr/bin/node (v26.10.0) and require('../lib/cli.js') misses. That matches the log exactly. The fix is to make the app resolve the system node under /usr (which the sandbox binds fully). Let me check the repo's node requirement before changing anything.

The app's PATH has fnm v22 first, /usr/bin later. Let me confirm the app's exact resolution and that the system node works in the sandbox against your real project.

Confirmed: the app picks fnm's v22 node (/root/.local/share/fnm/.../bin/node). Let me prove system npm works fully inside the sandbox, then fix the PATH resolution.

System npm 12.2.0 and node v26.10.0 both work perfectly in the sandbox — the only problem is which node your app picks. Let me (1) commit the revert you asked for, and (2) fix the PATH resolution.

Revert committed (eccaa5f79). Now the environment fix: make your shell/app resolve the system Node under /usr (which the sandbox binds wholesale) instead of fnm, without touching code.

Shims are in place and resolve to system v26.10.0 / npm 12.2.0. The app process was restarted/closed meanwhile — let me re-check it and prove the full path end-to-end in the sandbox against your real project.

The fix is verified end-to-end. Let me confirm the repo state.

搞定了,两件事都办了。

1. 回退了日志改动

eccaa5f79 回退了我那个 6311bb583:application.log 恢复成对所有行统一脱敏绝对路径,application.log 里不会再出现明文 host 路径。工作区干净,只剩你本来就改过的 .env 没动。

2. 真正的坑在环境:应用挑到了 fnm 的 Node,而 sandbox 只认 /usr 下的 Node

日志里 Node.js v26.10.0 是系统 node,但出错的是 fnm v22 的 npm,两个被拼到一起了。链路是:

  • 你 app 进程的 PATH 是 /root/.local/bin:/run/user/0/fnm_multishells/1117_.../bin:...:/usr/bin,所以 resolve_node_runtime 先挑中 fnm v22.23.3;
  • Linux sandbox 对工具链只做两件事:--ro-bind /usr /usr 整棵绑,和「非 /usr 可执行文件只单文件挂载」。fnm 在 /root/.local/share/fnm/...,于是 bwrap 里只挂了 <fnm>/bin/npm 这一个文件,fm 的 node 和 node_modules/npm/lib 都不在;
  • 那个 npm shim 的 #!/usr/bin/env node 在 sandbox 里找不到 /usr/bin 都没排到的 fnm node,就落到了 /usr/bin/node(v26.10.0),然后 require('../lib/cli.js') 去 <fnm>/lib/cli.js 找 → Cannot find module '../lib/cli.js'。跟你贴的报错一模一样。

没动代码,改的是环境:在 PATH 最前面的 /root/.local/bin 里建了指向系统 Node 的软链:

/root/.local/bin/node -> /usr/bin/node   (v26.10.0)
/root/.local/bin/npm  -> /usr/bin/npm    (12.2.0)
/root/.local/bin/npx  -> /usr/bin/npx

因为 /usr 是 sandbox 整棵只读绑定的,系统 node/npm 在沙箱里天然完整。验证:

  • 你正在跑的 runner(PID 321684)现在解析出的就是 /usr/bin/node + /usr/lib/node_modules/npm/bin/npm-cli.js;
  • 我用 bwrap 按同样的绑定点在你的 click/game 里跑了 npm run,正常列出 build / dev,退出码 0。

直接回 app 里重试 npm run build 就行,不用重启(Node 是每条命令现解析的)。

一个副作用,先说清楚

/root/.local/bin 在 PATH 最前面,所以新起的进程(包括你这个终端)node 会变成 v26、npm 变成 12.2.0,不再用 fnm v22。仓库没有 engines/.nvmrc 约束,一般没事;如果 dev 栈在 v26 上出幺蛾子,一条命令回退:

rm /root/.local/bin/node /root/.local/bin/npm /root/.local/bin/npx

(已经在跑的 Vite dev server 用的是 fnm v22,不受影响,只有新命令走系统 node。)

另外:现在 npm run 在 sandbox 里能过,说明之前那条 bwrap: Can't find source path 大概率也是同一个「fnm 路径被单文件挂载」引发的边角,等真复现了我们再看。要不要我把 sandbox 启动失败日志以默认脱敏的版本重新加回来?那个不影响脱敏策略。

Understood. Two things: (1) get my commit out of your tree, (2) fix the environment rather than the code. Let me check what this host's Node setup actually looks like while I revert my commit. I'm on your machine (`k88936-t14p`). I can see it: your active `node` is **fnm** v22.23.3, but there's also a system `/usr/bin/node`. Let me pin down which one the app picked and whether the system npm is complete. `/usr/bin/node` is v26.10.0 — that's the one the app used. But look at the system npm: `bin/npm-cli.js` is only **54 bytes** and `lib/cli.js` is **407 bytes**. Those are stubs, not real npm. Let me read them. These are real npm 12.2.0 files, and `/usr/bin/npm --version` works on the host. So the sandbox is the problem. Let me read exactly how bwrap is assembled. Let me stop theorizing and reproduce directly — I'm root on the host and can run `bwrap` with the same binds the app uses. The minimal bwrap test shows `/usr/bin/npm` actually loads fine under `--ro-bind /usr /usr` (it got past `../lib/cli.js`). So the app must be using a different npm. The app is running as PID 312426 — let me read its real environment. The app (PID 312426) has this PATH, with **fnm v22.23.3 first** and `/usr/bin` later: ``` /root/.local/bin:/run/user/0/fnm_multishells/1117_.../bin:...:/usr/bin:... ``` So `resolve_node_runtime` picks the **fnm** node. The sandbox then mounts only the fnm `npm` shim — no fnm `node`, no npm `lib/` — so the shim's `env node` falls through to `/usr/bin/node` (v26.10.0) and `require('../lib/cli.js')` misses. That matches the log exactly. The fix is to make the app resolve the **system** node under `/usr` (which the sandbox binds fully). Let me check the repo's node requirement before changing anything. The app's PATH has fnm v22 first, `/usr/bin` later. Let me confirm the app's exact resolution and that the system node works in the sandbox against your real project. Confirmed: the app picks fnm's v22 node (`/root/.local/share/fnm/.../bin/node`). Let me prove system npm works fully inside the sandbox, then fix the PATH resolution. System npm 12.2.0 and node v26.10.0 both work perfectly in the sandbox — the only problem is which `node` your app picks. Let me (1) commit the revert you asked for, and (2) fix the PATH resolution. Revert committed (`eccaa5f79`). Now the environment fix: make your shell/app resolve the system Node under `/usr` (which the sandbox binds wholesale) instead of fnm, without touching code. Shims are in place and resolve to system v26.10.0 / npm 12.2.0. The app process was restarted/closed meanwhile — let me re-check it and prove the full path end-to-end in the sandbox against your real project. The fix is verified end-to-end. Let me confirm the repo state. 搞定了,两件事都办了。 ## 1. 回退了日志改动 `eccaa5f79` 回退了我那个 `6311bb583`:`application.log` 恢复成对所有行统一脱敏绝对路径,`application.log` 里不会再出现明文 host 路径。工作区干净,只剩你本来就改过的 `.env` 没动。 ## 2. 真正的坑在环境:应用挑到了 fnm 的 Node,而 sandbox 只认 `/usr` 下的 Node 日志里 `Node.js v26.10.0` 是**系统** node,但出错的是 **fnm v22** 的 npm,两个被拼到一起了。链路是: - 你 app 进程的 PATH 是 `/root/.local/bin:/run/user/0/fnm_multishells/1117_.../bin:...:/usr/bin`,所以 `resolve_node_runtime` 先挑中 **fnm v22.23.3**; - Linux sandbox 对工具链只做两件事:`--ro-bind /usr /usr` 整棵绑,和「非 `/usr` 可执行文件只单文件挂载」。fnm 在 `/root/.local/share/fnm/...`,于是 bwrap 里**只挂了 `<fnm>/bin/npm` 这一个文件**,fm 的 `node` 和 `node_modules/npm/lib` 都不在; - 那个 npm shim 的 `#!/usr/bin/env node` 在 sandbox 里找不到 `/usr/bin` 都没排到的 fnm node,就落到了 `/usr/bin/node`(v26.10.0),然后 `require('../lib/cli.js')` 去 `<fnm>/lib/cli.js` 找 → `Cannot find module '../lib/cli.js'`。跟你贴的报错一模一样。 **没动代码,改的是环境**:在 PATH 最前面的 `/root/.local/bin` 里建了指向系统 Node 的软链: ``` /root/.local/bin/node -> /usr/bin/node (v26.10.0) /root/.local/bin/npm -> /usr/bin/npm (12.2.0) /root/.local/bin/npx -> /usr/bin/npx ``` 因为 `/usr` 是 sandbox 整棵只读绑定的,系统 node/npm 在沙箱里天然完整。验证: - 你正在跑的 runner(PID 321684)现在解析出的就是 `/usr/bin/node` + `/usr/lib/node_modules/npm/bin/npm-cli.js`; - 我用 bwrap 按同样的绑定点在你的 `click/game` 里跑了 `npm run`,正常列出 `build` / `dev`,退出码 0。 直接回 app 里重试 `npm run build` 就行,不用重启(Node 是每条命令现解析的)。 ## 一个副作用,先说清楚 `/root/.local/bin` 在 PATH 最前面,所以**新起的进程**(包括你这个终端)`node` 会变成 v26、`npm` 变成 12.2.0,不再用 fnm v22。仓库没有 `engines`/`.nvmrc` 约束,一般没事;如果 dev 栈在 v26 上出幺蛾子,一条命令回退: ``` rm /root/.local/bin/node /root/.local/bin/npm /root/.local/bin/npx ``` (已经在跑的 Vite dev server 用的是 fnm v22,不受影响,只有新命令走系统 node。) 另外:现在 `npm run` 在 sandbox 里能过,说明之前那条 `bwrap: Can't find source path` 大概率也是同一个「fnm 路径被单文件挂载」引发的边角,等真复现了我们再看。要不要我把 sandbox 启动失败日志以**默认脱敏**的版本重新加回来?那个不影响脱敏策略。
k88936 self-assigned this 2026-10-07 10:38:51 +08:00
k88936 changed title from support fnm to support fnm nvm 2026-10-07 10:38:58 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GenarrativeAI/Genarrative#648