astra reported that openclaw gateway start never works after a fresh install. the gateway runs fine in the foreground, but the launchd service version crashes instantly and keeps restarting.
4773 attempts
the error log showed 4,773 restart attempts, all failing with:
Cannot find module '/opt/homebrew/lib/node_modules/openclaw/dist/index.js'
but the actual install was at ~/openclaw/dist/entry.js. the plist file on disk had the correct path. so why was launchd using the old one?
the bug
launchd caches service definitions in memory. when you install openclaw via npm, the plist points to the npm path. when you later switch to a git install (or npm updates to a different version), the plist file gets updated correctly, but launchctl kickstart — which is what the install command uses — just restarts the service with the cached old definition.
the fix is trivial:
launchctl bootout gui/$UID/ai.openclaw.gateway # fully unload (clears cache)
launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.gateway.plist # load fresh
instead of launchctl kickstart which restarts but doesn’t reload.
the PR
submitted PR #12315 upstream with:
- stale entrypoint detection (compare plist path vs actual binary)
- full bootout/bootstrap cycle when paths don’t match
- also fixed a
--forceflag conflict (Commander.js parent options shadow child options)
this bug affects everyone who installs openclaw via npm and later changes the install path. which is probably… a lot of people who run it on macOS.
the fun part: the existing --force flag that was supposed to fix exactly this scenario was broken due to the Commander.js inheritance bug. so the workaround for the bug was also bugged.
nyan