Skip to content

Bug: openclaw gateway status false positive on Windows due to setlocal batch parsing bug #53474

@chinazll

Description

@chinazll

Description

Running openclaw gateway install on Windows creates a Scheduled Task. After installation, openclaw gateway status reports:

Service config issue: Service command does not include the gateway subcommand
Command: setlocal enabledelayedexpansion
Service file: C:\Users\<username>\.openclaw\gateway.cmd

Steps to reproduce

  1. Run openclaw gateway install
  2. Run openclaw gateway status or openclaw doctor

Expected behavior

No audit warnings; the gateway service configuration is validated successfully.

Actual behavior

openclaw gateway status reports a gatewayCommandMissing audit issue.


Root Cause

The bug is in src/daemon/schtasks.tsreadScheduledTaskCommand().

How the function works

readScheduledTaskCommand() reads gateway.cmd, iterates line by line, skips @echo off, rem comments, and set environment lines (checking if (lower.startsWith("set "))), then captures the first real executable line as the command:

@echo off
setlocal enabledelayedexpansion
set "PORT=18789"
set "NODE=C:\Program Files\nodejs\node.exe"
set "SCRIPT=..."
...
start "" "%NODE%" "%SCRIPT%" gateway --port %PORT%

The bug

The parser checks if (lower.startsWith("set ")) — note the trailing space. setlocal does NOT start with set (it starts with setlocal), so setlocal enabledelayedexpansion is not skipped. It is incorrectly captured as the first executable line → commandLine = "setlocal enabledelayedexpansion".

This is passed to parseCmdScriptCommandLine(), producing:

programArguments: ["setlocal", "enabledelayedexpansion"]

The audit check

In systemd-hints.ts:

function hasGatewaySubcommand(programArguments) {
  return Boolean(programArguments?.some((arg) => arg === "gateway"));
}

Since neither "setlocal" nor "enabledelayedexpansion" equals "gateway", hasGatewaySubcommand() returns falsefalse positive gatewayCommandMissing audit error.

The actual task is fine

schtasks /query /fo LIST correctly shows C:\Users\...\gateway.cmd as the task's Program. The gateway runs correctly — this is purely a validation/audit false positive caused by the batch file parsing logic.


The Fix

In src/daemon/schtasks.ts, readScheduledTaskCommand():

// Before:
if (lower.startsWith("set ")) {

// After:
if (lower.startsWith("set ") || lower.startsWith("setlocal")) {

This ensures setlocal enabledelayedexpansion is correctly treated as a batch environment declaration and skipped, allowing the actual start "" "%NODE%" "%SCRIPT%" gateway --port %PORT% line to be captured.


Environment

  • OS: Windows 10.0.22631 (x64)
  • Username: any (non-ASCII username is NOT required to reproduce)
  • OpenClaw version: 2026.3.23-2
  • Node.js: 24.14.0

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