openclaw - ✅(Solved) Fix [Feature]: Prefer Volta shim path over version-pinned Volta node path for macOS gateway LaunchAgent [1 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#52184Fetched 2026-04-08 01:14:35
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Timeline (top)
commented ×1cross-referenced ×1

On macOS, openclaw gateway install / service generation can pin the gateway LaunchAgent to a version-specific Volta Node path such as:

/Users/<user>/.volta/tools/image/node/24.14.0/bin/node

For users who intentionally manage Node with Volta, this is more brittle than necessary. A better choice would be the Volta shim path:

/Users/<user>/.volta/bin/node

Root Cause

  1. Use bare node
    • weaker because launchd PATH may differ from the interactive shell, and there is already prior art showing that bare node can fail under launchd

Fix Action

Fixed

PR fix notes

PR #52252: fix(daemon): prefer Volta shim path over version-pinned image path

Description (problem / solution / changelog)

Summary

Fixes #52184.

When resolveStableNodePath encounters a Volta tools/image path such as ~/.volta/tools/image/node/24.14.0/bin/node, it now resolves to the stable Volta shim at ~/.volta/bin/node instead. If the shim is not accessible the original path is returned unchanged.

Root Cause

resolveStableNodePath already handles Homebrew Cellar paths (/opt/homebrew/Cellar/node/VERSION/bin/node → /opt/homebrew/opt/node/bin/node) following #32185, but had no equivalent handling for Volta. Volta's tools/image directory stores one concrete directory per pinned version; the version-specific path becomes stale when the pin changes, leaving the LaunchAgent / systemd unit pointing at an old binary.

The stable Volta shim (~/.volta/bin/node) delegates to whichever version is currently active and survives version upgrades without needing the service to be reinstalled.

Changes

  • src/infra/stable-node-path.ts — detect ~/.volta/tools/image/node/<v>/bin/node[.exe] and resolve to ~/.volta/bin/node[.exe] when accessible
  • src/infra/stable-node-path.test.ts — two new tests:
    1. shim accessible → resolved to shim
    2. shim not accessible → original path returned

Testing

 RUN  v4.1.0 /Users/byungskersmacbook/Documents/GitHub/openclaw-contributing

✓ src/infra/stable-node-path.test.ts (5 tests) 7ms

 Test Files  1 passed (1)  Tests  5 passed (5)  Start at  21:51:08  Duration  146ms (transform 38ms, setup 44ms, import 10ms, tests 7ms, environment 0ms)

 RUN  v4.1.0 /Users/byungskersmacbook/Documents/GitHub/openclaw-contributing

✓ src/daemon/runtime-paths.test.ts (17 tests) 7ms

 Test Files  1 passed (1)  Tests  17 passed (17)  Start at  21:51:09  Duration  166ms (transform 55ms, setup 43ms, import 32ms, tests 7ms, environment 0ms)

Pre-existing pnpm check errors (@mariozechner/pi-agent-core, zod, @sinclair/typebox) are unrelated to this change.

Changed files

  • src/infra/stable-node-path.test.ts (modified, +36/-0)
  • src/infra/stable-node-path.ts (modified, +22/-0)

Code Example

<key>ProgramArguments</key>
<array>
  <string>/Users/xiaomu/.volta/tools/image/node/24.14.0/bin/node</string>
  <string>/Users/xiaomu/.volta/tools/image/packages/openclaw/lib/node_modules/openclaw/dist/index.js</string>
  <string>gateway</string>
  <string>--port</string>
  <string>18789</string>
</array>

---

/Users/xiaomu/.volta/bin/node

---

<key>ProgramArguments</key>
<array>
  <string>/Users/xiaomu/.volta/tools/image/node/24.14.0/bin/node</string>
  <string>/Users/xiaomu/.volta/tools/image/packages/openclaw/lib/node_modules/openclaw/dist/index.js</string>
  <string>gateway</string>
  <string>--port</string>
  <string>18789</string>
</array>

---

/Users/xiaomu/.volta/bin/node
RAW_BUFFERClick to expand / collapse

Summary

On macOS, openclaw gateway install / service generation can pin the gateway LaunchAgent to a version-specific Volta Node path such as:

/Users/<user>/.volta/tools/image/node/24.14.0/bin/node

For users who intentionally manage Node with Volta, this is more brittle than necessary. A better choice would be the Volta shim path:

/Users/<user>/.volta/bin/node

Problem to solve

OpenClaw currently generates a LaunchAgent that may bind the gateway service to a version-specific Volta-managed Node installation directory.

That works initially, but it creates unnecessary fragility for users who intentionally rely on Volta:

  • reinstalling or regenerating the gateway service can rewrite the plist back to a historical Node version path
  • later Volta-managed upgrades may leave the LaunchAgent pointing at an outdated concrete path
  • users who want to keep using a version manager still need a stable absolute path for launchd

Observed generated entry on macOS:

<key>ProgramArguments</key>
<array>
  <string>/Users/xiaomu/.volta/tools/image/node/24.14.0/bin/node</string>
  <string>/Users/xiaomu/.volta/tools/image/packages/openclaw/lib/node_modules/openclaw/dist/index.js</string>
  <string>gateway</string>
  <string>--port</string>
  <string>18789</string>
</array>

In the same environment, the Volta shim path exists and works:

/Users/xiaomu/.volta/bin/node

This is not a request to stop supporting version managers. It is a request to use the more stable Volta shim path when Volta is the chosen Node manager.

Proposed solution

When generating the macOS gateway LaunchAgent, choose the Node executable with a path selection strategy like this:

  1. If a stable system-level Node exists (for example /opt/homebrew/bin/node), use that absolute path.
  2. Else if Volta is detected, prefer the Volta shim path: /Users/<user>/.volta/bin/node
  3. Only fall back to a version-pinned Volta installation path if no better stable absolute path is available.

Why this helps:

  • launchd still gets an absolute executable path
  • Volta users remain on their version-manager workflow
  • the LaunchAgent is no longer pinned to a specific Volta Node version directory

Alternatives considered

  1. Use bare node

    • weaker because launchd PATH may differ from the interactive shell, and there is already prior art showing that bare node can fail under launchd
  2. Keep using the version-pinned Volta path

    • works initially, but is brittle after Node upgrades or service regeneration
  3. Require users to install a system-level Node

    • too invasive for users who intentionally standardized on Volta or another version manager

Impact

Affected: macOS users running OpenClaw gateway as a LaunchAgent while managing Node through Volta

Severity: Medium It does not always break immediately, but it makes the service configuration more fragile than necessary.

Frequency: Recurring whenever the gateway service is regenerated, reinstalled, or reviewed after Node version changes

Consequence:

  • LaunchAgent may remain pinned to a historical Volta Node version path
  • harder to reason about service stability after upgrades
  • extra manual repair work for users who rely on version managers

Evidence/examples

Observed LaunchAgent entry generated on macOS:

<key>ProgramArguments</key>
<array>
  <string>/Users/xiaomu/.volta/tools/image/node/24.14.0/bin/node</string>
  <string>/Users/xiaomu/.volta/tools/image/packages/openclaw/lib/node_modules/openclaw/dist/index.js</string>
  <string>gateway</string>
  <string>--port</string>
  <string>18789</string>
</array>

In the same environment, the stable Volta shim path exists and works:

/Users/xiaomu/.volta/bin/node

Related context from doctor/status output:

  • Gateway service uses Node from a version manager; it can break after upgrades.
  • System Node 22 LTS (22.16+) or Node 24 not found; install it before migrating away from version managers.

This suggests the risk is already recognized, but the generated LaunchAgent still chooses the more brittle version-pinned Volta path instead of the Volta shim path.

Additional information

This request tries to balance two existing constraints:

  • using bare node under launchd is fragile
  • using a version-pinned Volta path is also fragile

For Volta users, the shim path is the better compromise:

  • absolute path for launchd
  • still uses the chosen version manager
  • avoids hard-pinning the LaunchAgent to a specific Node version directory

This should remain backward-compatible for users who are not on Volta.

extent analysis

Fix Plan

To address the issue, we need to modify the LaunchAgent generation to prefer the Volta shim path when Volta is detected. Here are the steps:

  1. Detect Volta installation: Check if Volta is installed by looking for the .volta directory in the user's home directory.
  2. Get the Volta shim path: If Volta is detected, get the path to the Volta shim by running which node in the terminal or by constructing the path manually (e.g., /Users/<user>/.volta/bin/node).
  3. Update the LaunchAgent: Modify the LaunchAgent generation to use the Volta shim path instead of the version-pinned Volta path.

Example code snippet in JavaScript:

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

// Detect Volta installation
const voltaDir = path.join(process.env.HOME, '.volta');
if (fs.existsSync(voltaDir)) {
  // Get the Volta shim path
  const voltaShimPath = path.join(voltaDir, 'bin', 'node');
  // Update the LaunchAgent
  const launchAgentPath = '/path/to/launch/agent.plist';
  const launchAgentContent = fs.readFileSync(launchAgentPath, 'utf8');
  const updatedLaunchAgentContent = launchAgentContent.replace(/\/Users\/[^\/]+\/\.volta\/tools\/image\/node\/[^\/]+\/bin\/node/, voltaShimPath);
  fs.writeFileSync(launchAgentPath, updatedLaunchAgentContent);
}

Verification

To verify that the fix worked, check the generated LaunchAgent file and ensure that it uses the Volta shim path instead of the version-pinned Volta path.

Example:

<key>ProgramArguments</key>
<array>
  <string>/Users/xiaomu/.volta/bin/node</string>
  <string>/Users/xiaomu/.volta/tools/image/packages/openclaw/lib/node_modules/openclaw/dist/index.js</string>
  <string>gateway</string>
  <string>--port</string>
  <string>18789</string>
</array>

Extra Tips

  • Make sure to test the fix on different environments and Node versions to ensure compatibility.
  • Consider adding a fallback mechanism to handle cases where the Volta shim path is not available.
  • Document the changes and update any relevant documentation to reflect the new behavior.

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 [Feature]: Prefer Volta shim path over version-pinned Volta node path for macOS gateway LaunchAgent [1 pull requests, 1 comments, 2 participants]