Summary
On macOS, repairLaunchAgentBootstrap() still appears to kickstart the OpenClaw gateway LaunchAgent when launchctl bootstrap reports that the service is already loaded. If the service is already loaded and running, repair should return success instead of forcing a kickstart/restart.
This is adjacent to, but narrower than, #40905. That issue covered openclaw gateway restart re-bootstrap behavior. This report is specifically about the repair/install path's already-loaded branch.
Environment
- OpenClaw:
2026.5.3-1 (2eae30e)
- Platform: macOS
26.4.1 arm64
- Node:
22.22.1
- Gateway service: LaunchAgent
ai.openclaw.gateway
- Gateway path:
/opt/homebrew/lib/node_modules/openclaw/dist/index.js gateway --port 18789
Current Behavior
In the current compiled launchd bundle:
async function repairLaunchAgentBootstrap(args) {
...
const boot = await execLaunchctl([
"bootstrap",
domain,
plistPath
]);
let repairStatus = "repaired";
if (boot.code !== 0) {
const detail = (boot.stderr || boot.stdout).trim();
if (!isLaunchctlAlreadyLoaded(boot)) return {
ok: false,
status: "bootstrap-failed",
detail: detail || void 0
};
repairStatus = "already-loaded";
}
if (repairStatus === "repaired") return {
ok: true,
status: repairStatus
};
const kick = await execLaunchctl(["kickstart", serviceTarget]);
...
}
So if bootstrap fails only because the LaunchAgent is already loaded, the code proceeds to:
launchctl kickstart gui/$UID/ai.openclaw.gateway
Expected Behavior
If bootstrap reports already loaded, repairLaunchAgentBootstrap() should inspect the runtime state. If the loaded service is already running, it should return success:
{"ok":true,"status":"already-loaded"}
It should only kickstart if the service is already loaded but not running or otherwise unhealthy.
Why This Matters
The repair path can be used during update/doctor/install flows. Unconditionally kickstarting an already-running service can:
- interrupt an otherwise healthy gateway
- disconnect WebUI/Discord sessions unnecessarily
- fail under macOS permission/context constraints even when no repair was needed
- make repair/install behavior look broken while the service is actually fine
Local Patch Previously Used
We have carried this local patch for earlier OpenClaw versions and it still appears applicable in 2026.5.3-1.
Suggested minimal upstream change:
if (repairStatus === "already-loaded") {
const runtime = await readLaunchAgentRuntime(env).catch(() => null);
if (runtime?.status === "running") return {
ok: true,
status: repairStatus
};
}
const kick = await execLaunchctl(["kickstart", serviceTarget]);
This keeps the existing kickstart behavior for non-running already-loaded services, while avoiding an unnecessary restart when the service is already loaded and running.
Validation / Local Evidence
Current 2026.5.3-1 code still contains the unconditional already-loaded -> kickstart path:
/opt/homebrew/lib/node_modules/openclaw/dist/launchd-BVs6hych.js
repairLaunchAgentBootstrap(...)
repairStatus = "already-loaded"
const kick = await execLaunchctl(["kickstart", serviceTarget])
The gateway itself is healthy after normal restart:
OpenClaw status --all:
Gateway service LaunchAgent installed · loaded · running
Gateway reachable on ws://127.0.0.1:18789
Suggested Upstream Fix
In repairLaunchAgentBootstrap():
- Detect
already-loaded.
- Call
readLaunchAgentRuntime(env).
- If runtime status is
running, return success without kickstart.
- Keep the existing
kickstart fallback only for loaded-but-not-running states.
Summary
On macOS,
repairLaunchAgentBootstrap()still appears to kickstart the OpenClaw gateway LaunchAgent whenlaunchctl bootstrapreports that the service is already loaded. If the service is already loaded and running, repair should return success instead of forcing a kickstart/restart.This is adjacent to, but narrower than, #40905. That issue covered
openclaw gateway restartre-bootstrap behavior. This report is specifically about the repair/install path'salready-loadedbranch.Environment
2026.5.3-1(2eae30e)26.4.1arm6422.22.1ai.openclaw.gateway/opt/homebrew/lib/node_modules/openclaw/dist/index.js gateway --port 18789Current Behavior
In the current compiled
launchdbundle:So if
bootstrapfails only because the LaunchAgent is already loaded, the code proceeds to:Expected Behavior
If
bootstrapreports already loaded,repairLaunchAgentBootstrap()should inspect the runtime state. If the loaded service is already running, it should return success:{"ok":true,"status":"already-loaded"}It should only kickstart if the service is already loaded but not running or otherwise unhealthy.
Why This Matters
The repair path can be used during update/doctor/install flows. Unconditionally kickstarting an already-running service can:
Local Patch Previously Used
We have carried this local patch for earlier OpenClaw versions and it still appears applicable in
2026.5.3-1.Suggested minimal upstream change:
This keeps the existing kickstart behavior for non-running already-loaded services, while avoiding an unnecessary restart when the service is already loaded and running.
Validation / Local Evidence
Current
2026.5.3-1code still contains the unconditional already-loaded -> kickstart path:The gateway itself is healthy after normal restart:
Suggested Upstream Fix
In
repairLaunchAgentBootstrap():already-loaded.readLaunchAgentRuntime(env).running, return success withoutkickstart.kickstartfallback only for loaded-but-not-running states.