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:
- Run a local token-auth gateway with a paired CLI device.
- Run
openclaw gateway probe --json or openclaw status --json.
- 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:
- keep the minimal
status-only probe detail path, or
- 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.
Summary
Local loopback
gateway probe/statuscan falsely reportmissing scope: operator.readeven when the CLI device is already paired withoperator.readandoperator.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:
2026.3.13tokenws://127.0.0.1:18789operator.admin,operator.approvals,operator.pairing,operator.read,operator.writeSteps:
openclaw gateway probe --jsonoropenclaw status --json.missing scope: operator.readeven though the paired device token includes that scope.Root cause
In
src/gateway/probe.ts, loopback probes explicitly passdeviceIdentity: null: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.readscope 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
nulldevice identity on loopback probes, the false scope warning disappeared, but the probe then became timeout-prone because it does:healthstatussystem-presenceconfig.getin one probe session.
On my machine, a single
statusRPC 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:
statusfor probe detailsChanged files:
src/gateway/probe.tssrc/gateway/probe.test.tsdocs/cli/gateway.mdFocused tests passed:
Result after patch
Before:
openclaw gateway probe --json=>degraded: true,missing scope: operator.readopenclaw status --json=>gateway.reachable: false,error: "missing scope: operator.read"After:
openclaw gateway probe --json=>ok: true,degraded: false,rpcOk: trueopenclaw status --json=>gateway.reachable: true,error: nullopenclaw gateway status=>RPC probe: okSuggested direction
At minimum, loopback probes should not force
deviceIdentity: null.For the detail path, I think there are two viable fixes:
status-only probe detail path, orThe first option is the smallest reliable fix and matches the current status consumers well.