Skip to content

Bug: gateway restart spawns duplicate processes on Windows (3 windows) #52044

@andyk-ms

Description

@andyk-ms

Bug: gateway restart spawns duplicate gateway processes on Windows (3 windows)

Summary

openclaw gateway restart on Windows produces 3 cmd windows instead of 1:

  1. The original gateway window (being shut down)
  2. A new window from the CLI's schtasks /Run
  3. A third window from the gateway's self-restart script

The second and third race for the port — one succeeds, the other fails with "port already in use" and exits.

Root Cause

During openclaw gateway restart, two independent mechanisms both try to start a new gateway:

  1. CLI path (daemon-cli.js): restartScheduledTask() does schtasks /End then schtasks /Run
  2. Self-restart path (restart-C7ane9OU.js): The dying gateway process fires relaunchGatewayScheduledTask(), which spawns a detached .cmd script (openclaw-schtasks-restart-<uuid>.cmd) that retries schtasks /Run up to 12 times with 1s delay

The self-restart mechanism exists for commands.restart: true (config-change auto-restart), but it also fires during a CLI-initiated restart, causing a duplicate start.

Code trace

CLI restart (daemon-cli.js:19646):

async function restartScheduledTask({ stdout, env }) {
    await execSchtasks(["/End", "/TN", taskName]);
    // No delay
    const res = await execSchtasks(["/Run", "/TN", taskName]);  // ← Start #1
}

Self-restart on shutdown (restart-C7ane9OU.js:282):

function buildScheduledTaskRestartScript(taskName) {
    // Writes a .cmd that retries schtasks /Run up to 12 times  ← Start #2
}

function relaunchGatewayScheduledTask(env) {
    spawn("cmd.exe", ["/d", "/s", "/c", scriptPath], {
        detached: true,
        stdio: "ignore",
        windowsHide: true
    }).unref();
}

Additionally, daemon-cli.js:22416 has a postRestartCheck that detects the old PID as "stale" (because includeUnknownListenersAsStale: process.platform === "win32") and can trigger a third service.restart() call.

Expected Behavior

openclaw gateway restart should produce exactly 1 new gateway window. Either:

  • The CLI should signal "CLI-initiated restart" so the shutdown handler skips self-restart, OR
  • restartScheduledTask should not call schtasks /Run and rely on the self-restart script, OR
  • Add a small delay between /End and /Run and wait for the old PID to exit

Reproduction

openclaw gateway start
# Wait for gateway to be healthy
openclaw gateway restart
# Observe: 3 cmd windows appear (original + 2 new)

100% reproducible.

Workaround

Use openclaw gateway stop followed by openclaw gateway start instead of restart.

Environment

  • OpenClaw v2026.3.8
  • Windows 10 (build 26200)
  • Node.js v24.14.0
  • commands.restart: true in config
  • Gateway managed via "OpenClaw Gateway" scheduled task

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions