Skip to content

gateway probe drops loopback device identity and can falsely report missing operator.read #46014

@Brafton-Sales

Description

@Brafton-Sales

Summary

Local loopback gateway probe / status can falsely report missing scope: operator.read even when the CLI device is already paired with operator.read and operator.write.

The immediate cause is that the probe client disables device identity on loopback connects, which makes the gateway clear requested scopes for the unbound connection. After fixing that, the current probe path can still time out because it tries to fetch four detail RPCs on the same probe connection.

Repro

Environment where I hit this:

  • OpenClaw 2026.3.13
  • gateway auth mode: token
  • local loopback gateway at ws://127.0.0.1:18789
  • CLI device already paired with operator.admin, operator.approvals, operator.pairing, operator.read, operator.write

Steps:

  1. Run a local token-auth gateway with a paired CLI device.
  2. Run openclaw gateway probe --json or openclaw status --json.
  3. Observe degraded output like missing scope: operator.read even though the paired device token includes that scope.

Root cause

In src/gateway/probe.ts, loopback probes explicitly pass deviceIdentity: null:

const disableDeviceIdentity = (() => {
  try {
    return isLoopbackHost(new URL(opts.url).hostname);
  } catch {
    return false;
  }
})();

// ...
deviceIdentity: disableDeviceIdentity ? null : undefined,

On the server side, unbound connections have their requested scopes cleared in the WS handshake path. That means the loopback probe successfully connects, but its requested operator.read scope is stripped before detail RPC runs. The result is a false degraded warning.

Follow-on issue after fixing device identity

Once I removed the forced null device identity on loopback probes, the false scope warning disappeared, but the probe then became timeout-prone because it does:

  • health
  • status
  • system-presence
  • config.get

in one probe session.

On my machine, a single status RPC was enough for the probe/status surfaces, but the full four-call detail path could push the probe past its 3s budget.

Tested fix

I validated this source patch locally:

  • keep device identity enabled for loopback probes
  • fetch only status for probe details

Changed files:

  • src/gateway/probe.ts
  • src/gateway/probe.test.ts
  • docs/cli/gateway.md

Focused tests passed:

corepack pnpm exec vitest run src/gateway/probe.test.ts
corepack pnpm exec vitest run src/commands/gateway-status.test.ts src/commands/status.scan.test.ts

Result after patch

Before:

  • openclaw gateway probe --json => degraded: true, missing scope: operator.read
  • openclaw status --json => gateway.reachable: false, error: "missing scope: operator.read"

After:

  • openclaw gateway probe --json => ok: true, degraded: false, rpcOk: true
  • openclaw status --json => gateway.reachable: true, error: null
  • openclaw gateway status => RPC probe: ok

Suggested direction

At minimum, loopback probes should not force deviceIdentity: null.

For the detail path, I think there are two viable fixes:

  1. keep the minimal status-only probe detail path, or
  2. keep richer detail fetches but make them budget-aware instead of firing four probe RPCs in one short probe window.

The first option is the smallest reliable fix and matches the current status consumers well.

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