From 3d3796243f7d986fbb24bfe943990cd3b8f56cbf Mon Sep 17 00:00:00 2001 From: pick-cat Date: Sun, 12 Jul 2026 06:59:12 +0800 Subject: [PATCH] docs(gateway): add launchd supervisor loop troubleshooting (#89816) * docs(gateway): add launchd supervisor loop troubleshooting * docs(gateway): warn before disabling node LaunchAgent * chore: trigger CI after rebase onto main Co-Authored-By: Claude Opus 4.7 * docs(gateway): modernize launchd recovery runbook --------- Co-authored-by: Claude Opus 4.7 Co-authored-by: Peter Steinberger --- docs/docs_map.md | 1 + docs/gateway/troubleshooting.md | 96 +++++++++++++++++++++++++++ docs/platforms/mac/bundled-gateway.md | 4 ++ 3 files changed, 101 insertions(+) diff --git a/docs/docs_map.md b/docs/docs_map.md index cf399d02b9fb..a382a0899b7d 100644 --- a/docs/docs_map.md +++ b/docs/docs_map.md @@ -3962,6 +3962,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`. - H3: Auth detail codes quick map - H2: Gateway service not running - H2: macOS gateway silently stops responding, then resumes when you touch the dashboard + - H2: macOS launchd supervisor loop with duplicate gateway/node LaunchAgents - H2: Gateway exits during high memory use - H2: Gateway rejected invalid config - H2: Gateway probe warnings diff --git a/docs/gateway/troubleshooting.md b/docs/gateway/troubleshooting.md index 905817077902..0813797fac8a 100644 --- a/docs/gateway/troubleshooting.md +++ b/docs/gateway/troubleshooting.md @@ -483,6 +483,102 @@ Related: - [Logging](/logging) - [Doctor](/gateway/doctor) +## macOS launchd supervisor loop with duplicate gateway/node LaunchAgents + +Use this when a macOS install keeps restarting every few seconds, `openclaw` +health checks flap between healthy and unavailable, and channel dispatch stalls +even though the service appears to be running. + +This was observed on older installs where both `ai.openclaw.gateway` and +`ai.openclaw.node` LaunchAgents were active and each injected +`OPENCLAW_LAUNCHD_LABEL`. In that state OpenClaw can detect launchd +supervision, try to hand restart back to launchd, and fall into a fast +`EADDRINUSE`/respawn loop instead of one stable gateway process. + +```bash +for i in 1 2 3 4; do + ps aux | grep 'openclaw.*index.js' | grep -v grep | awk '{print $2}' + sleep 10 +done + +openclaw gateway status --deep +openclaw node status +launchctl print gui/$UID/ai.openclaw.gateway | grep -E 'state|last exit|runs' +tail -n 80 ~/Library/Logs/openclaw/gateway.log +``` + +Look for: + +- More than one gateway PID across the 30-second sample instead of one stable + process. +- `EADDRINUSE`, `another gateway instance is already listening`, or repeated + restart/handoff lines in `gateway.log`. +- Both `~/Library/LaunchAgents/ai.openclaw.gateway.plist` and + `~/Library/LaunchAgents/ai.openclaw.node.plist` loaded at the same time on a + host that should only run one managed gateway service. + +What to do: + +1. If this host should only run the Gateway service, remove the managed node + service through OpenClaw. **Skip this step** if you actively rely on the node + service for remote node features; uninstalling it stops those features on + this host: + + ```bash + openclaw node uninstall + ``` + +2. Install a persistent Gateway wrapper that clears the inherited launchd + markers before starting OpenClaw. Use the supported `--wrapper` option; do + not edit the generated file under `~/.openclaw/service-env/`, because service + reinstall, update, and doctor repair regenerate that file: + + ```bash + mkdir -p ~/.local/bin + cat >~/.local/bin/openclaw-launchd-workaround <<'EOF' + #!/bin/sh + set -eu + unset OPENCLAW_LAUNCHD_LABEL LAUNCH_JOB_LABEL LAUNCH_JOB_NAME XPC_SERVICE_NAME || true + exec openclaw "$@" + EOF + chmod 700 ~/.local/bin/openclaw-launchd-workaround + + openclaw gateway install \ + --wrapper ~/.local/bin/openclaw-launchd-workaround \ + --force + ``` + + `gateway install` persists the wrapper path across forced reinstalls, + updates, and doctor repairs. + +3. Verify that the Gateway is stable and serving RPC, not merely listening: + + ```bash + openclaw gateway status --deep --require-rpc + + for i in 1 2 3 4; do + ps aux | grep 'openclaw.*index.js' | grep -v grep | awk '{print $2}' + sleep 10 + done + ``` + + The PID sample should show one stable process instead of a rotating set of + PIDs, and inbound channel dispatch should resume. + +4. After upgrading to a release where the underlying dual-LaunchAgent loop is + fixed, remove the workaround and reinstall the normal managed service: + + ```bash + OPENCLAW_WRAPPER= openclaw gateway install --force + rm ~/.local/bin/openclaw-launchd-workaround + ``` + +Related: + +- [macOS platform notes](/platforms/mac/bundled-gateway) +- [Doctor](/gateway/doctor) +- [Gateway CLI](/cli/gateway) + ## Gateway exits during high memory use Use when the Gateway disappears under load, the supervisor reports an OOM-style restart, or logs mention `critical memory pressure bundle written`. diff --git a/docs/platforms/mac/bundled-gateway.md b/docs/platforms/mac/bundled-gateway.md index c2ab9fe6e6be..1d1e809297ef 100644 --- a/docs/platforms/mac/bundled-gateway.md +++ b/docs/platforms/mac/bundled-gateway.md @@ -61,6 +61,10 @@ Logging: - launchd stdout: `~/Library/Logs/openclaw/gateway.log` (profiles use `gateway-.log`) - launchd stderr: suppressed +- If the host loops with repeated `EADDRINUSE` or fast restarts, check for + duplicate `ai.openclaw.gateway` / `ai.openclaw.node` LaunchAgents and the + launchd-marker workaround in + [Gateway troubleshooting](/gateway/troubleshooting#macos-launchd-supervisor-loop-with-duplicate-gatewaynode-launchagents). ## Version compatibility