Summary
openclaw gateway install --force is not idempotent. When invoked while a gateway instance is already running, it spawns a new process without first stopping the existing one, immediately hitting EADDRINUSE on port 18789. The new instance fails to bind, but the old instance keeps running with inconsistent service registration state.
Repro
On a host with an active gateway instance:
openclaw gateway install --force
Observed
From openclaw log (2026-04-26, 5060Ti):
Gateway failed to start: another gateway instance is already listening on ws://127.0.0.1:18789
listen EADDRINUSE: address already in use 127.0.0.1:18789
pid 437908: node.exe
Gateway service appears registered. Stop it first.
Tip: openclaw gateway stop
After this, openclaw daemon status --json reports runtime.status=stopped (split-brain — see companion issue), but port 18789 still has the old node.exe listening.
bonjour watchdog also goes into a re-advertise loop, presumably due to torn mDNS announcement state.
Expected
--force should:
- Detect existing instance (registered service or port listener on 18789)
- Run the equivalent of
gateway stop
- Poll until port 18789 has no listener (with a sane timeout — e.g. 30s)
- Only then spawn the new instance
If step 3 times out, surface a clear error rather than spawning a doomed second instance.
Impact
Discovered during downstream ship verification (anro-claw issue #825). The workaround for downstream consumers is "don't run --force during verification flows; assume the gateway is already ready" — but --force not being idempotent surprises anyone treating it as a safe re-run.
Companion issue (filed separately): daemon status --json mis-reports stopped when port 18789 has a listener but service registration is torn — should report conflict with the offending PID.
Environment
- Windows 11, Node 20 (bundled)
- Observed on 5060Ti dev box during 2026-04-26 ship of downstream installer
Summary
openclaw gateway install --forceis not idempotent. When invoked while a gateway instance is already running, it spawns a new process without first stopping the existing one, immediately hittingEADDRINUSEon port 18789. The new instance fails to bind, but the old instance keeps running with inconsistent service registration state.Repro
On a host with an active gateway instance:
Observed
From
openclawlog (2026-04-26, 5060Ti):After this,
openclaw daemon status --jsonreportsruntime.status=stopped(split-brain — see companion issue), but port 18789 still has the old node.exe listening.bonjour watchdog also goes into a re-advertise loop, presumably due to torn mDNS announcement state.
Expected
--forceshould:gateway stopIf step 3 times out, surface a clear error rather than spawning a doomed second instance.
Impact
Discovered during downstream ship verification (anro-claw issue #825). The workaround for downstream consumers is "don't run
--forceduring verification flows; assume the gateway is already ready" — but--forcenot being idempotent surprises anyone treating it as a safe re-run.Companion issue (filed separately):
daemon status --jsonmis-reportsstoppedwhen port 18789 has a listener but service registration is torn — should reportconflictwith the offending PID.Environment