openclaw - 💡(How to fix) Fix openclaw update leaves running gateway broken: stale ESM chunk paths cause ERR_MODULE_NOT_FOUND [1 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#68610Fetched 2026-04-19 15:09:36
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants
  • Platform: macOS 26.3 (Mac mini, Mac16,10)
  • OpenClaw: 2026.4.15 (upgraded from 2026.4.12)
  • Node.js: 25.6.1
  • Install path: /opt/homebrew/lib/node_modules/openclaw
  • Gateway log path: /tmp/openclaw/openclaw-2026-04-18.log
  • Launchd plist: ~/Library/LaunchAgents/ai.openclaw.gateway.plist

Error Message

[gateway] request handler failed: Error: Cannot find module '/opt/homebrew/lib/node_modules/openclaw/dist/audit-membership-runtime-JFfG3LQ2.js' imported from '/opt/homebrew/lib/node_modules/openclaw/dist/audit-CUW7rxcz.js': code=ERR_MODULE_NOT_FOUND ... [gateway] signal SIGTERM received [gateway] received SIGTERM; shutting down

Root Cause

Have the gateway watch its own dist/ directory and process.exit() on change, so KeepAlive picks it up. Rejected because:

  • Races with in-flight updates (you can get mid-write restarts)
  • Adds fs watcher overhead for a rare event
  • Doesn't fix the root problem (old CLI can't restart the gateway from outside)

Fix Action

Fix / Workaround

Current workaround

Code Example

[gateway] request handler failed: Error: Cannot find module
'/opt/homebrew/lib/node_modules/openclaw/dist/audit-membership-runtime-JFfG3LQ2.js'
imported from '/opt/homebrew/lib/node_modules/openclaw/dist/audit-CUW7rxcz.js':
code=ERR_MODULE_NOT_FOUND
...
[gateway] signal SIGTERM received
[gateway] received SIGTERM; shutting down

---

alias openclaw-update='openclaw update \
  && launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist 2>/dev/null \
  ;  launchctl kickstart -k gui/$(id -u)/ai.openclaw.gateway 2>/dev/null'

---

// at the end of the update command, after dist/ has been written
import { execSync } from 'node:child_process'
import { getuid } from 'node:process'

function launchdLabelRegistered(label: string): boolean {
  try {
    execSync(`launchctl print gui/${getuid()}/${label}`, { stdio: 'ignore' })
    return true
  } catch {
    return false
  }
}

const label = 'ai.openclaw.gateway'
if (process.platform === 'darwin' && launchdLabelRegistered(label)) {
  console.log('Restarting gateway to pick up new dist chunks…')
  try {
    // bootstrap is idempotent; kickstart -k is a clean kill+respawn
    execSync(`launchctl bootstrap gui/${getuid()} ~/Library/LaunchAgents/${label}.plist`, { stdio: 'ignore' })
  } catch {}
  execSync(`launchctl kickstart -k gui/${getuid()}/${label}`, { stdio: 'inherit' })
}
RAW_BUFFERClick to expand / collapse

What happens

openclaw update rewrites /opt/homebrew/lib/node_modules/openclaw/dist/ chunks with fresh content-hash filenames (e.g. audit-membership-runtime-JFfG3LQ2.js → new hash). But the still-running gateway has the old chunk paths cached in its ESM loader. First lazy-import after the update fails:

[gateway] request handler failed: Error: Cannot find module
'/opt/homebrew/lib/node_modules/openclaw/dist/audit-membership-runtime-JFfG3LQ2.js'
imported from '/opt/homebrew/lib/node_modules/openclaw/dist/audit-CUW7rxcz.js':
code=ERR_MODULE_NOT_FOUND
...
[gateway] signal SIGTERM received
[gateway] received SIGTERM; shutting down

Then a bootout → bootstrap race during the shutdown leaves launchd with no ai.openclaw.gateway registration, so KeepAlive can't auto-relaunch and the gateway stays dead until a human manually kickstarts it. This happened on my Mac Mini today going v2026.4.12 → v2026.4.15.

Current workaround

Users have to alias their way around it:

alias openclaw-update='openclaw update \
  && launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist 2>/dev/null \
  ;  launchctl kickstart -k gui/$(id -u)/ai.openclaw.gateway 2>/dev/null'

Which is fine but forgettable. Running plain openclaw update (which is what's documented and what muscle memory reaches for) produces a broken system.

Proposed fix

Fold the kickstart into the update subcommand. Rough sketch:

// at the end of the update command, after dist/ has been written
import { execSync } from 'node:child_process'
import { getuid } from 'node:process'

function launchdLabelRegistered(label: string): boolean {
  try {
    execSync(`launchctl print gui/${getuid()}/${label}`, { stdio: 'ignore' })
    return true
  } catch {
    return false
  }
}

const label = 'ai.openclaw.gateway'
if (process.platform === 'darwin' && launchdLabelRegistered(label)) {
  console.log('Restarting gateway to pick up new dist chunks…')
  try {
    // bootstrap is idempotent; kickstart -k is a clean kill+respawn
    execSync(`launchctl bootstrap gui/${getuid()} ~/Library/LaunchAgents/${label}.plist`, { stdio: 'ignore' })
  } catch {}
  execSync(`launchctl kickstart -k gui/${getuid()}/${label}`, { stdio: 'inherit' })
}

That way openclaw update is self-healing and no alias is needed.

For non-launchd setups (Linux/systemd) the same idea applies — detect the service manager and restart the service there.

Alternative approach considered

Have the gateway watch its own dist/ directory and process.exit() on change, so KeepAlive picks it up. Rejected because:

  • Races with in-flight updates (you can get mid-write restarts)
  • Adds fs watcher overhead for a rare event
  • Doesn't fix the root problem (old CLI can't restart the gateway from outside)

Post-restart approach in the CLI is simpler and correct.

Context

  • Platform: macOS 26.3 (Mac mini, Mac16,10)
  • OpenClaw: 2026.4.15 (upgraded from 2026.4.12)
  • Node.js: 25.6.1
  • Install path: /opt/homebrew/lib/node_modules/openclaw
  • Gateway log path: /tmp/openclaw/openclaw-2026-04-18.log
  • Launchd plist: ~/Library/LaunchAgents/ai.openclaw.gateway.plist

extent analysis

TL;DR

The proposed fix involves modifying the openclaw update command to automatically restart the gateway service after updating the dist/ directory to ensure the new chunk paths are picked up.

Guidance

  • To implement the proposed fix, integrate the provided TypeScript code into the update subcommand of the openclaw CLI, ensuring it restarts the gateway service using launchctl after updating the dist/ directory.
  • Verify the fix by running openclaw update and checking if the gateway service restarts automatically and picks up the new chunk paths without errors.
  • For non-launchd setups (e.g., Linux/systemd), adapt the restart logic to detect and restart the service using the respective service manager.
  • Consider adding error handling and logging to the restart logic to improve robustness and debugging capabilities.

Example

The provided TypeScript code snippet demonstrates how to restart the gateway service using launchctl:

import { execSync } from 'node:child_process'
import { getuid } from 'node:process'

// ...

execSync(`launchctl kickstart -k gui/${getuid()}/${label}`, { stdio: 'inherit' })

This code can be integrated into the update subcommand to automate the restart process.

Notes

The proposed fix assumes a macOS environment with launchd. For other platforms, the restart logic will need to be adapted to the respective service manager (e.g., systemd on Linux).

Recommendation

Apply the proposed workaround by integrating the restart logic into the openclaw update command, as it provides a self-healing solution that eliminates the need for manual intervention or aliases.

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