← Back to PRs

#20272: fix: LaunchAgent KeepAlive causes restart loop (fixes #20257)

by MisterGuy420 open 2026-02-18 18:31 View on GitHub →
app: macos gateway size: XS trusted-contributor
## Bug Summary When both LaunchAgent (KeepAlive: true) and the App's GatewayLaunchAgentManager manage the gateway lifecycle, they conflict — causing a restart loop, duplicate processes, and 100% CPU. This is because KeepAlive: true tells launchd to restart the gateway whenever it exits (for any reason). Combined with the App's periodic SIGUSR1 signals (issue #10600), this creates a continuous restart loop. ## Root Cause - `KeepAlive: true` in the LaunchAgent plist causes launchd to restart gateway on every exit - App sends periodic SIGUSR1 signals every 8-11 minutes (issue #10600) - Each SIGUSR1 triggers gateway restart, which launchd immediately restarts due to KeepAlive: true - Results in continuous restart loop, duplicate processes, 100% CPU ## Fix 1. Changed `KeepAlive: true` to `KeepAlive: { SuccessfulExit: false }` — only restart on crash (non-zero exit), not on intentional stop 2. Added `ThrottleInterval: 5` to prevent exponential backoff on crash loops (related to issue #4632) ## Testing - [x] pnpm install - [x] pnpm build - [x] pnpm check (format + lint + typecheck) - [x] pnpm test (launchd tests pass) --- **AI-assisted code** - This fix was generated by an automated bug-fix agent. <!-- greptile_comment --> <h3>Greptile Summary</h3> Changes the LaunchAgent `KeepAlive` setting from `true` to `{ SuccessfulExit: false }` and adds `ThrottleInterval: 5` to prevent restart loops caused by launchd restarting the gateway on every exit (including intentional SIGUSR1-triggered restarts). The template is also reformatted from a single-line string to a multi-line template literal for readability. - **Service audit regression**: `src/daemon/service-audit.ts:173` uses a regex that only matches `KeepAlive` followed by `<true/>`. After this change, the plist uses a dict-based `KeepAlive`, so the audit will emit false-positive `"LaunchAgent is missing KeepAlive=true"` warnings for every correctly-configured installation. The audit check needs to be updated to accept the new format. - **macOS app divergence**: `apps/macos/Sources/OpenClaw/LaunchAgentManager.swift:44` still generates `KeepAlive: true` in its own plist. If the macOS app's LaunchAgent has the same restart-loop issue, it should be updated as well for consistency. <h3>Confidence Score: 2/5</h3> - This PR introduces a regression in the service audit system that will produce false-positive warnings for all installations - The core KeepAlive and ThrottleInterval changes are correct and well-motivated, but the PR does not update the service-audit.ts regex that validates plist contents. After this change, every correctly-configured installation will be flagged with a spurious 'LaunchAgent is missing KeepAlive=true' warning. This is a functional regression that needs to be addressed before merging. - `src/daemon/service-audit.ts` needs its KeepAlive regex updated to accept the new dict-based format. `apps/macos/Sources/OpenClaw/LaunchAgentManager.swift` may also need the same KeepAlive change for consistency. <sub>Last reviewed commit: 34d8426</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs