← Back to PRs

#11327: fix(launchd): reload plist from disk on restartLaunchAgent

by caiop91 open 2026-02-07 18:07 View on GitHub →
gateway
## Summary `restartLaunchAgent()` uses only `launchctl kickstart -k`, which restarts the process but does **not** reload the plist from disk. After `openclaw update` rewrites the plist with new environment variables (e.g., `OPENCLAW_SERVICE_VERSION`), launchd continues using the stale in-memory definition. ## Fix When the plist file exists on disk, `restartLaunchAgent` now performs a full cycle: 1. `launchctl bootout` — unload the old definition 2. `launchctl enable` — clear any persisted disabled state 3. `launchctl bootstrap` — load the new plist from disk 4. `launchctl kickstart -k` — start the process This matches the pattern already used by `installLaunchAgent()`. Falls back to kickstart-only when no plist is found on disk. ## Testing - Verified the source matches the minified `dist/service-BZesBIaG.js` (lines 292-302) - The fix follows the same bootout → enable → bootstrap → kickstart pattern used in `installLaunchAgent()` - Fallback to kickstart-only preserves behavior when plist is absent Fixes #11324 ## Related - #8790 — Version mismatch between `gateway run` and launchctl service - #3780 — `gateway stop` uses `bootout`, breaking subsequent `gateway start` <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This change updates `restartLaunchAgent()` to reload a LaunchAgent plist from disk when it exists, by running a `bootout → enable → bootstrap → kickstart -k` cycle. If the plist isn’t present, it preserves the prior behavior and only runs `kickstart -k`. The intent matches the pattern already used in `installLaunchAgent()` to ensure updated plist contents (notably environment variables) take effect after `openclaw update`. <h3>Confidence Score: 4/5</h3> - Mostly safe to merge, but error handling in the new restart path can misreport success and mask launchctl failures. - The change is localized and follows an existing install pattern, but it introduces a concrete behavioral bug: in the plist-present branch, several launchctl commands’ non-zero exit codes are ignored, so the CLI can claim a restart succeeded when it didn’t. - src/daemon/launchd.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs