Bug
openclaw gateway restart always times out after 60 seconds on any Linux system without lsof installed, even though the gateway is running and healthy.
Severity: HIGH — affects every restart on Arch Linux, Alpine, minimal Debian/Ubuntu, containers, and any distro that doesn't ship lsof by default.
Reproduction
- Uninstall
lsof (or use a system that doesn't have it)
- Run
openclaw gateway restart
- Observe: timeout after 60s with error:
Timed out after 60s waiting for gateway port 18789 to become healthy.
Port 18789 is already in use.
- Port is in use but process details are unavailable (install lsof or run as an admin user).
Port diagnostics errors: Error: spawn lsof ENOENT
Gateway restart timed out after 60s waiting for health checks.
- The gateway is actually running fine —
curl http://127.0.0.1:18789/health returns 200.
Root Cause
In src/cli/daemon-cli/restart-health.ts, the ownsPort logic:
const ownsPort =
runtimePid != null
? portUsage.listeners.some((listener) => listenerOwnedByRuntimePid({ listener, runtimePid }))
: gatewayListeners.length > 0 ||
(portUsage.status === "busy" && portUsage.listeners.length === 0);
When lsof is missing, inspectPortUsage() returns { status: "busy", listeners: [] }. The runtimePid != null branch calls .some() on an empty array → always false → ownsPort = false → healthy = false → loops for 120 attempts × 500ms = 60s timeout.
The runtimePid == null branch already has the correct fallback (portUsage.status === "busy" && portUsage.listeners.length === 0), but the runtimePid != null branch is missing it.
Fix
PR: #32613
Bug
openclaw gateway restartalways times out after 60 seconds on any Linux system withoutlsofinstalled, even though the gateway is running and healthy.Severity: HIGH — affects every restart on Arch Linux, Alpine, minimal Debian/Ubuntu, containers, and any distro that doesn't ship
lsofby default.Reproduction
lsof(or use a system that doesn't have it)openclaw gateway restartcurl http://127.0.0.1:18789/healthreturns 200.Root Cause
In
src/cli/daemon-cli/restart-health.ts, theownsPortlogic:When
lsofis missing,inspectPortUsage()returns{ status: "busy", listeners: [] }. TheruntimePid != nullbranch calls.some()on an empty array → alwaysfalse→ownsPort = false→healthy = false→ loops for 120 attempts × 500ms = 60s timeout.The
runtimePid == nullbranch already has the correct fallback(portUsage.status === "busy" && portUsage.listeners.length === 0), but theruntimePid != nullbranch is missing it.Fix
PR: #32613