#21591: fix(update): prevent double restart when refreshing service env
cli
size: XS
Cluster:
Gateway Restart Improvements
## Problem
`runDaemonInstall({ force: true })` calls `installLaunchAgent` which performs `launchctl bootout + bootstrap + kickstart -k`, restarting the service itself. The code introduced in #21071 then also ran `runRestartScript` (another `kickstart -k`) or `runDaemonRestart`, causing two competing restarts that each trigger startup hooks (e.g. `BOOT.md`).
**Observed symptoms:**
- 5 duplicate on-boot notifications after `openclaw update`
- 3 duplicate on-boot notifications after `openclaw gateway restart`
- `gateway.err.log` shows repeated `gateway already running (pid …); lock timeout after 5000ms` from launchctl racing with itself
## Root Cause
In `maybeRestartService`, after `runDaemonInstall` succeeds (which internally does `kickstart -k`), the code continued to execute `runRestartScript` (which also does `kickstart -k` after a 1 s delay). This is a regression from 20004711d which removed the `serviceRefreshed` guard that originally prevented the double-restart.
## Fix
Set `restartInitiated = true` after a successful `runDaemonInstall` so the subsequent `runRestartScript` / `runDaemonRestart` branches are skipped — the service has already been restarted by the install's `kickstart`.
```
runDaemonInstall (kickstart ✓) → skip runRestartScript → skip runDaemonRestart
```
The fallback paths still work:
- If `runDaemonInstall` **throws**, `restartInitiated` stays `false` and the existing fallback runs (`runDaemonRestart` on failure, as tested).
- If `refreshServiceEnv` is false, the restart-script / daemon-restart paths run as before.
## Testing
- Updated two tests to match the corrected behavior.
- All 44 update-cli tests pass.
- `pnpm check` format: ✅ (TS2742 errors in other files are pre-existing, unrelated to this change)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Prevents duplicate service restarts during `openclaw update` by setting `restartInitiated = true` after successful `runDaemonInstall`.
- Fixed regression from commit 20004711d which removed the `serviceRefreshed` guard
- `runDaemonInstall` internally performs `launchctl kickstart -k` (confirmed in `src/daemon/launchd.ts:403`), making additional restarts redundant
- Adds conditional guards (`!restartInitiated &&`) to skip `runRestartScript` and `runDaemonRestart` when install already restarted the service
- Preserves fallback behavior: if `runDaemonInstall` throws, `restartInitiated` stays false and normal restart paths execute
- Updated tests correctly verify the new behavior across all paths
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with high confidence
- The fix correctly addresses a clear regression with a simple, well-scoped change. The logic is sound across all code paths, the root cause analysis is accurate (verified by examining git history and the `installLaunchAgent` implementation), and comprehensive test coverage validates both the fix and fallback behavior. No security concerns or edge cases identified.
- No files require special attention
<sub>Last reviewed commit: 0d162b9</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#19857: fix(launchd): self-heal restart when service is unloaded
by vibecodooor · 2026-02-18
81.8%
#11327: fix(launchd): reload plist from disk on restartLaunchAgent
by caiop91 · 2026-02-07
81.2%
#16845: fix(daemon): gateway auto-restart on SIGTERM + agent restart guidel...
by kiminbean · 2026-02-15
79.2%
#16170: fix: restart service manager after update.run
by Swader · 2026-02-14
78.7%
#20272: fix: LaunchAgent KeepAlive causes restart loop (fixes #20257)
by MisterGuy420 · 2026-02-18
77.9%
#16016: fix: update systemd unit version on gateway restart
by jbold · 2026-02-14
77.5%
#22304: Gateway: fix launchd start after stop
by apethree · 2026-02-21
76.8%
#13084: fix(daemon): multi-layer defense against zombie gateway processes
by openperf · 2026-02-10
76.8%
#17237: fix(update): guard post-install imports after npm global update
by tdjackey · 2026-02-15
75.4%
#16185: fix: patch systemd unit version before service restart
by nozh · 2026-02-14
75.0%