Why
- Only one gateway process should own a state directory; run additional gateways with isolated profiles, state directories, configs, and ports.
- Survive crashes/SIGKILL without leaving stale lock files behind.
- Fail fast with a clear error when another gateway already owns the port.
Three layers
Startup enforces ownership in three steps, in order:- State ownership lock acquires a lock keyed by the canonical state directory. Every Gateway participates, including Gateways started with
OPENCLAW_ALLOW_MULTI_GATEWAY=1, so destructive SQLite maintenance cannot race a live owner. - Config lock acquires the historical per-config lock and records the runtime port. Multi-Gateway mode skips this config singleton but retains the state ownership lock.
- Socket bind binds the HTTP/WebSocket listener (default
ws://127.0.0.1:18789) as an exclusive TCP listener.
GatewayLockError.
State and config locks
- Lock liveness comes from the recorded PID, platform process start identity when available, and Gateway process identity. A verified owner remains authoritative during startup before its port begins listening.
- A dedicated SQLite coordinator serializes metadata inspection, stale-owner reclamation, and lock replacement. Its exclusive transaction is released automatically if the owning process crashes.
- If a lock file is missing or the recorded owner process is gone, startup reclaims the lock and continues.
-
If either lock is actively held, startup retries for up to 5 seconds (default) before giving up:
Socket bind
-
On
EADDRINUSE, startup retries the bind for up to 20 attempts at 500ms intervals (roughly 10 seconds total) to ride out aTIME_WAITwindow after a recently exited process. -
If the port is still in use after retries:
-
Other bind failures:
Operational notes
- If the port is occupied by a different, non-gateway process, the error is the same; free the port or choose another with
openclaw gateway --port <port>. OPENCLAW_ALLOW_MULTI_GATEWAY=1permits multiple config/runtime instances, not shared mutable state. Each instance still needs a uniqueOPENCLAW_STATE_DIR.- Under a service supervisor, a new gateway process that hits either error above first probes
/healthzon the existing process. If that process is healthy, the new process leaves it in control instead of failing. On systemd, it exits with code78; the unit’sRestartPreventExitStatus=78stopsRestart=alwaysfrom looping on a lock orEADDRINUSEconflict. If the existing process never becomes healthy, the health-probe retry is time-bounded and startup then fails with the lock error above instead of looping forever. - The macOS app keeps its own lightweight PID guard before spawning the gateway; the file lock and socket bind above are the actual runtime enforcement.
Related
- Multiple Gateways - running multiple instances with unique ports
- Troubleshooting - diagnosing
EADDRINUSEand port conflicts