Skip to content

CLI can leave orphan openclaw-gateway processes on Linux/systemd when gateway.mode=local #39222

Description

@ottopan

Summary

openclaw CLI commands can leave behind orphan openclaw / openclaw-gateway processes on Linux when gateway.mode is local and a systemd-managed gateway is already running.

This can lead to:

  • duplicate gateway processes
  • port 18789 conflicts
  • Gateway already running locally / another gateway instance is already listening errors
  • operational instability when using otherwise documented commands like openclaw gateway restart or certain openclaw agent flows

Environment

  • OpenClaw version: 2026.2.24
  • OS: Linux
  • Service manager: systemd --user
  • Gateway service installed as openclaw-gateway.service
  • Gateway mode: local
  • Gateway auth: token

Service setup

The installed systemd unit is:

[Service]
ExecStart=/root/.nvm/versions/node/v24.13.0/bin/node /root/.nvm/versions/node/v24.13.0/lib/node_modules/openclaw/dist/index.js gateway run --port 18789
Restart=always
Environment=OPENCLAW_STATE_DIR=/root/.openclaw
Environment=OPENCLAW_CONFIG_PATH=/root/.openclaw/openclaw.json
Environment=OPENCLAW_GATEWAY_PORT=18789
Environment=OPENCLAW_NO_RESPAWN=1

Observed behavior

Even with the systemd-managed gateway already running, some CLI commands cause extra unmanaged processes like:

openclaw
└─ openclaw-gateway

These extra processes are not the systemd service process. They can survive as orphaned or detached processes and race the systemd-managed gateway for port 18789.

Reproduction

Not every command reproduces 100% of the time, but I observed this during flows involving:

  1. openclaw gateway restart
  2. openclaw agent --local ...
  3. openclaw agent ... when gateway-based execution fails and the CLI falls back to embedded mode

After running those, ps often shows:

<systemd-managed gateway>
openclaw
openclaw-gateway

and logs/CLI output show one or more of:

Gateway failed to start: gateway already running (pid ...)
Gateway failed to start: another gateway instance is already listening on ws://127.0.0.1:18789
Port 18789 is already in use.
Gateway already running locally. Stop it (openclaw gateway stop) or use a different port.

Expected behavior

If a systemd-managed gateway is already installed and running:

  • CLI commands should reuse it, or
  • cleanly signal/restart it through the supervisor, or
  • fail without spawning detached unmanaged gateway processes

They should not leave behind orphan openclaw / openclaw-gateway processes.

Relevant code paths

Two places seem especially relevant:

  1. register.agent-*.js

openclaw agent first tries gateway execution and then falls back to embedded mode:

try {
  return await agentViaGatewayCommand(opts, runtime);
} catch (err) {
  runtime.error?.(`Gateway agent failed; falling back to embedded: ${String(err)}`);
  return await agentCommand(localOpts, runtime, deps);
}
  1. gateway-cli-*.js

Gateway restart/close handling can respawn a detached child unless OPENCLAW_NO_RESPAWN=1 is present:

if (isTruthy(process.env.OPENCLAW_NO_RESPAWN)) return { mode: "disabled" };
if (isLikelySupervisedProcess(process.env)) return { mode: "supervised" };
const child = spawn(process.execPath, args, {
  env: process.env,
  detached: true,
  stdio: "inherit"
});
child.unref();

This looks unsafe for CLI-invoked flows that are not themselves running under systemd, even when a supervised gateway already exists.

Workaround

Current workarounds are:

  • use systemctl --user restart openclaw-gateway.service instead of openclaw gateway restart
  • avoid openclaw agent --local on affected systems
  • run CLI commands with OPENCLAW_NO_RESPAWN=1 when possible

Question

Would you consider:

  1. disabling detached respawn when an installed/running gateway service already exists
  2. making openclaw gateway restart delegate to the supervisor more strictly on systemd setups
  3. preventing openclaw agent fallback paths from creating unmanaged local gateway processes on hosts that already have a supervised gateway

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions