Summary
openclaw CLI can connect successfully to a local loopback gateway over shared token auth, but the session lands in a scope-limited operator state and RPC calls fail with errors like:
missing scope: operator.read
missing scope: operator.write
This breaks control-plane operations such as:
openclaw gateway probe
openclaw cron add
openclaw cron runs
Environment
- OpenClaw package version:
2026.3.13
- Gateway mode:
local
- Gateway bind:
loopback
- Gateway auth mode:
token
- Target URL:
ws://127.0.0.1:18789
- CLI invoked from Cedric via
exec, using the local openclaw CLI
Repro
From the same machine as the gateway:
openclaw gateway probe --token <gateway-token> --url ws://127.0.0.1:18789
Observed result:
- transport/auth connect succeeds
- but probe reports degraded RPC auth, e.g.
Reachable: yes
Connect: ok
RPC: limited - missing scope: operator.read
And in gateway logs we see:
[ws] ⇄ res ✗ status 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ system-presence 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ config.get 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
Same class of failure affects cron add / cron runs through the same path.
What we checked already
1. Pairing/auth files looked correct
We verified both of these files contained operator scopes including read/write:
~/.openclaw/identity/device-auth.json
~/.openclaw/devices/paired.json
Scopes present:
operator.admin
operator.approvals
operator.pairing
operator.read
operator.write
We also restarted the gateway after correcting a mismatch there. The problem persisted.
2. Internal code path investigation
The installed code suggests this local-loopback path intentionally avoids attaching device identity for token/password-authenticated gateway calls.
In our local build we found:
Client side
dist/auth-profiles-*.js
function shouldAttachDeviceIdentityForGatewayCall(params) {
if (!(params.token || params.password)) return true;
try {
const parsed = new URL(params.url);
return ![
"127.0.0.1",
"::1",
"localhost"
].includes(parsed.hostname);
} catch {
return true;
}
}
And the gateway client is built with:
deviceIdentity: shouldAttachDeviceIdentityForGatewayCall({
url,
token,
password
}) ? loadOrCreateDeviceIdentity() : void 0,
Server side
dist/gateway-cli-*.js
We found:
function roleCanSkipDeviceIdentity(role, sharedAuthOk) {
return role === "operator" && sharedAuthOk;
}
and missing-device handling that can clear scopes when no bound device is present:
const clearUnboundScopes = () => {
if (scopes.length > 0) {
scopes = [];
connectParams.scopes = scopes;
}
};
This appears to produce an awkward state where:
- shared auth succeeds
- connection is allowed
- but effective operator scopes end up empty / limited
- so subsequent RPC authorization fails
3. Temporary local patch attempt
As a diagnostic only, we patched shouldAttachDeviceIdentityForGatewayCall(...) to always return true in the installed dist bundles.
That still did not fully fix the issue.
So the problem seems deeper than only the loopback identity gate.
Current diagnosis
Most likely the CLI is ending up in a partially authorized operator session on this loopback shared-auth path:
- connect succeeds
- operator role is accepted
- but the client does not arrive with a fully usable device-token-backed scope set for RPC
- and the client does not automatically upgrade/retry out of this degraded state
In other words:
local loopback + shared token auth can connect, but still leave the operator client scope-limited for gateway RPC.
Why this matters
This blocks a robust local operator workflow where the local openclaw CLI is expected to safely perform:
- cron registration
- cron inspection
- gateway probe/status
- other control-plane operations
Without this, local automation that depends on control-plane CLI operations becomes much harder to make reliable.
Questions / expected behavior
I think one of these should be true:
- Local loopback shared-auth operator CLI calls should attach device identity and establish a fully scoped operator session, or
- Local shared-auth operator CLI calls that are intentionally allowed without device identity should still preserve requested operator scopes for RPC, or
- The CLI should detect this degraded state and explicitly retry/upgrade into a device-token-backed operator session instead of silently succeeding at connect and failing later on read/write/admin RPCs.
Request
Could you confirm whether this is expected behavior or a bug?
If it is a bug, I’d appreciate guidance on the intended fix path for:
- local loopback token-authenticated operator CLI
- from the same machine as the gateway
- where downstream RPC methods need full operator scopes
If useful, I can also provide a smaller repro focused only on gateway probe.
Summary
openclawCLI can connect successfully to a local loopback gateway over shared token auth, but the session lands in a scope-limited operator state and RPC calls fail with errors like:missing scope: operator.readmissing scope: operator.writeThis breaks control-plane operations such as:
openclaw gateway probeopenclaw cron addopenclaw cron runsEnvironment
2026.3.13localloopbacktokenws://127.0.0.1:18789exec, using the localopenclawCLIRepro
From the same machine as the gateway:
Observed result:
And in gateway logs we see:
Same class of failure affects
cron add/cron runsthrough the same path.What we checked already
1. Pairing/auth files looked correct
We verified both of these files contained operator scopes including read/write:
~/.openclaw/identity/device-auth.json~/.openclaw/devices/paired.jsonScopes present:
operator.adminoperator.approvalsoperator.pairingoperator.readoperator.writeWe also restarted the gateway after correcting a mismatch there. The problem persisted.
2. Internal code path investigation
The installed code suggests this local-loopback path intentionally avoids attaching device identity for token/password-authenticated gateway calls.
In our local build we found:
Client side
dist/auth-profiles-*.jsAnd the gateway client is built with:
Server side
dist/gateway-cli-*.jsWe found:
and missing-device handling that can clear scopes when no bound device is present:
This appears to produce an awkward state where:
3. Temporary local patch attempt
As a diagnostic only, we patched
shouldAttachDeviceIdentityForGatewayCall(...)to always returntruein the installed dist bundles.That still did not fully fix the issue.
So the problem seems deeper than only the loopback identity gate.
Current diagnosis
Most likely the CLI is ending up in a partially authorized operator session on this loopback shared-auth path:
In other words:
local loopback + shared token auth can connect, but still leave the operator client scope-limited for gateway RPC.
Why this matters
This blocks a robust local operator workflow where the local
openclawCLI is expected to safely perform:Without this, local automation that depends on control-plane CLI operations becomes much harder to make reliable.
Questions / expected behavior
I think one of these should be true:
Request
Could you confirm whether this is expected behavior or a bug?
If it is a bug, I’d appreciate guidance on the intended fix path for:
If useful, I can also provide a smaller repro focused only on
gateway probe.