openclaw - ✅(Solved) Fix Linux service PATH resolver checks $FNM_DIR/current/bin but modern fnm uses $FNM_DIR/aliases/default/bin (Darwin resolver is correct) [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#68169Fetched 2026-04-18 05:53:38
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
cross-referenced ×2commented ×1referenced ×1

Root Cause

resolveLinuxUserBinDirs in src/daemon/runtime-paths.ts (compiled into dist/runtime-paths-*.js) appends current/bin under FNM_DIR:

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "current/bin"));
dirs.push(`${home}/.fnm/current/bin`);

whereas the Darwin resolver correctly uses the modern persistent-default path:

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "aliases/default/bin"));
dirs.push(`${home}/Library/Application Support/fnm/aliases/default/bin`);
dirs.push(`${home}/.fnm/aliases/default/bin`);

$FNM_DIR/current/ is a session-local symlink that fnm only creates when fnm use runs in an interactive shell. It is not part of a persistent fnm install produced by fnm install <ver> + fnm alias <ver> default. Recent fnm versions don't create it at install time.

Fix Action

Fixed

PR fix notes

PR #68180: fix(daemon): add aliases/default/bin to Linux fnm PATH resolver (fixes #68169)

Description (problem / solution / changelog)

Fix issue #68169: Linux service PATH resolver now checks both aliases/default/bin (modern fnm) and current/bin (legacy fnm).

Changed files

  • src/acp/translator.ts (modified, +5/-1)
  • src/cron/isolated-agent/delivery-dispatch.ts (modified, +20/-1)
  • src/daemon/service-env.ts (modified, +3/-1)
  • src/slack/monitor/context.ts (modified, +1/-1)
  • src/telegram/send.ts (modified, +7/-1)

PR #68219: fix(daemon): resolve modern fnm aliases/default path on Linux service PATH

Description (problem / solution / changelog)

Summary

Fixes #68169 — `openclaw doctor` on Linux reported the gateway service PATH was missing required dirs for any fnm install that uses the modern persistent-default pattern (`fnm alias <ver> default`). `resolveLinuxUserBinDirs` in `src/daemon/service-env.ts` only probed `$FNM_DIR/current/bin` and `~/.fnm/current/bin`, both of which are session-local symlinks that fnm only creates when `fnm use <ver>` runs in an interactive shell. Systemd-managed gateway lifecycles never enter that shell, so the Node binary was effectively invisible.

Root cause

`resolveDarwinUserBinDirs` (same file, ~line 127) already walks both the modern `aliases/default/bin` and the legacy `current/bin` paths. `resolveLinuxUserBinDirs` was a straight mirror of the Darwin resolver except it only included `current/bin` for fnm — that asymmetry pre-dates the fnm upstream change where `alias <ver> default` became the recommended install pattern.

Fix

Mirror the Darwin pattern. Probe `$FNM_DIR/aliases/default/bin` first (the persistent modern path) and keep `$FNM_DIR/current/bin` afterwards for older installs that still rely on it. Do the same for the home-relative defaults:

  • `/.local/share/fnm/aliases/default/bin` + `/.local/share/fnm/current/bin`
  • `/.fnm/aliases/default/bin` + `/.fnm/current/bin`

Both paths coexist so older `fnm use`-only installs continue to work, and modern `fnm alias default` installs now resolve without needing an interactive shell.

Test plan

  • Added a dedicated regression test `resolves modern fnm aliases/default path on Linux even when current/bin is absent (#68169)` exercising the exact systemd scenario from the issue body.
  • Extended the default-path test (`includes user bin directories when HOME is set on Linux`) and the env-configured test (`includes env-configured bin roots when HOME is set on Linux`) to assert the new aliases paths.
  • `NODE_OPTIONS=--max-old-space-size=8192 npx tsc --noEmit` — 247 baseline on main, 247 on branch.
  • `pnpm exec oxlint` on both touched files — 0 warnings, 0 errors.

Local full vitest is blocked by pre-existing `test/non-isolated-runner.ts` drift (reproduces on `main`); CI exercises the new cases normally.

Risk

  • No existing path is removed — `current/bin` is preserved, so older installs that relied on it still resolve.
  • No cross-platform effect: `resolveDarwinUserBinDirs` and the Windows PATH path are untouched.
  • The test asserts the modern-install scenario passes without requiring `current/bin` on disk, pinning the regression so a future "cleanup" can't accidentally drop the aliases path.

Changed files

  • src/daemon/service-env.test.ts (modified, +32/-0)
  • src/daemon/service-env.ts (modified, +11/-1)

Code Example

Gateway service PATH missing required dirs:
  /home/<user>/.local/share/fnm/current/bin

---

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "current/bin"));
dirs.push(`${home}/.fnm/current/bin`);

---

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "aliases/default/bin"));
dirs.push(`${home}/Library/Application Support/fnm/aliases/default/bin`);
dirs.push(`${home}/.fnm/aliases/default/bin`);

---

curl -fsSL https://fnm.vercel.app/install | bash
fnm install 24.14.1
fnm alias 24.14.1 default
# Default Node now at $FNM_DIR/aliases/default/bin/node — correct setup
openclaw doctor  # reports /current/bin as missing

---

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "aliases/default/bin"));
addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "current/bin"));
dirs.push(`${home}/.fnm/aliases/default/bin`);
dirs.push(`${home}/.fnm/current/bin`);
RAW_BUFFERClick to expand / collapse

openclaw doctor on Linux reports

Gateway service PATH missing required dirs:
  /home/<user>/.local/share/fnm/current/bin

even on a correctly-configured fnm install where the default Node is set via fnm alias <version> default.

Root cause

resolveLinuxUserBinDirs in src/daemon/runtime-paths.ts (compiled into dist/runtime-paths-*.js) appends current/bin under FNM_DIR:

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "current/bin"));
dirs.push(`${home}/.fnm/current/bin`);

whereas the Darwin resolver correctly uses the modern persistent-default path:

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "aliases/default/bin"));
dirs.push(`${home}/Library/Application Support/fnm/aliases/default/bin`);
dirs.push(`${home}/.fnm/aliases/default/bin`);

$FNM_DIR/current/ is a session-local symlink that fnm only creates when fnm use runs in an interactive shell. It is not part of a persistent fnm install produced by fnm install <ver> + fnm alias <ver> default. Recent fnm versions don't create it at install time.

Reproduction

curl -fsSL https://fnm.vercel.app/install | bash
fnm install 24.14.1
fnm alias 24.14.1 default
# Default Node now at $FNM_DIR/aliases/default/bin/node — correct setup
openclaw doctor  # reports /current/bin as missing

Proposed fix

Mirror the Darwin resolver — have resolveLinuxUserBinDirs include both aliases/default/bin and current/bin (keeping current/bin for legacy installs that still use fnm use in a shell):

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "aliases/default/bin"));
addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "current/bin"));
dirs.push(`${home}/.fnm/aliases/default/bin`);
dirs.push(`${home}/.fnm/current/bin`);

Sharper consequence

If the user accepts doctor's "Update gateway service config to the recommended defaults now?" prompt, the regenerated unit drops the aliases/default/bin entry from PATH (because resolveLinuxUserBinDirs doesn't produce it), which breaks node resolution at gateway startup. This is a sharper consequence of the same bug — the "fix" actively breaks a working install.

Environment

  • openclaw 2026.4.15
  • fnm 1.39.0
  • Linux (Ubuntu 24.04)

extent analysis

TL;DR

The issue can be fixed by updating the resolveLinuxUserBinDirs function to include both aliases/default/bin and current/bin in the PATH.

Guidance

  • The root cause of the issue is the incorrect appending of current/bin under FNM_DIR in the resolveLinuxUserBinDirs function.
  • To verify the issue, run openclaw doctor and check if the Gateway service PATH is missing the required directories.
  • To mitigate the issue, update the resolveLinuxUserBinDirs function to include both aliases/default/bin and current/bin in the PATH, as proposed in the fix.
  • The proposed fix should be applied to the src/daemon/runtime-paths.ts file and then compiled into dist/runtime-paths-*.js.

Example

addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "aliases/default/bin"));
addNonEmptyDir(dirs, appendSubdir(env?.FNM_DIR, "current/bin"));
dirs.push(`${home}/.fnm/aliases/default/bin`);
dirs.push(`${home}/.fnm/current/bin`);

Notes

The issue is specific to Linux environments and is caused by the incorrect handling of the FNM_DIR environment variable. The proposed fix should resolve the issue, but it may not be applicable to all versions of openclaw and fnm.

Recommendation

Apply the proposed workaround by updating the resolveLinuxUserBinDirs function to include both aliases/default/bin and current/bin in the PATH. This should resolve the issue and prevent the Gateway service PATH from being broken.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Linux service PATH resolver checks $FNM_DIR/current/bin but modern fnm uses $FNM_DIR/aliases/default/bin (Darwin resolver is correct) [2 pull requests, 1 comments, 2 participants]