openclaw - 💡(How to fix) Fix TUI / gateway-client connects but RPC calls fail with `missing scope: operator.read` despite paired device/token showing full operator scopes [3 comments, 4 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#52085Fetched 2026-04-08 01:15:50
View on GitHub
Comments
3
Participants
4
Timeline
3
Reactions
0
Author
Timeline (top)
commented ×3

On a fresh local macOS install of OpenClaw, the TUI / gateway-client can connect to the local gateway, but scope-gated RPC calls fail with:

  • missing scope: operator.read

This happens even after:

  • fresh device auth reset
  • device token rotation with full operator scopes
  • removing + re-pairing the local device
  • clean gateway restart
  • explicit --token TUI launch

The on-disk pairing/token state shows the correct scopes, but runtime RPC auth still behaves as if operator.read is missing.

Root Cause

On a fresh local macOS install of OpenClaw, the TUI / gateway-client can connect to the local gateway, but scope-gated RPC calls fail with:

  • missing scope: operator.read

This happens even after:

  • fresh device auth reset
  • device token rotation with full operator scopes
  • removing + re-pairing the local device
  • clean gateway restart
  • explicit --token TUI launch

The on-disk pairing/token state shows the correct scopes, but runtime RPC auth still behaves as if operator.read is missing.

Code Example

openclaw devices rotate --device <deviceId> --role operator \
     --scope operator.read \
     --scope operator.write \
     --scope operator.approvals \
     --scope operator.pairing \
     --scope operator.admin

---

openclaw gateway restart

---

TOKEN=$(python3 - <<'PY'
   import json, os
   p=os.path.expanduser("~/.openclaw/openclaw.json")
   with open(p) as f:
       print(json.load(f)["gateway"]["auth"]["token"])
   PY
   )
   openclaw tui --url ws://127.0.0.1:18789 --token "$TOKEN"

---

[ws] ⇄ res ✗ status 0ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ system-presence 0ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ config.get 0ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read

---

[gateway] security audit: device access upgrade requested reason=scope-upgrade ... scopesFrom=operator.read scopesTo=operator.admin client=gateway-client

---

[ws] unauthorized ... client=openclaw-tui ui v2026.3.13 reason=token_mismatch
RAW_BUFFERClick to expand / collapse

Summary

On a fresh local macOS install of OpenClaw, the TUI / gateway-client can connect to the local gateway, but scope-gated RPC calls fail with:

  • missing scope: operator.read

This happens even after:

  • fresh device auth reset
  • device token rotation with full operator scopes
  • removing + re-pairing the local device
  • clean gateway restart
  • explicit --token TUI launch

The on-disk pairing/token state shows the correct scopes, but runtime RPC auth still behaves as if operator.read is missing.

Environment

  • OpenClaw version: 2026.3.13
  • OS: macOS 15.7.4 arm64
  • Node: 25.8.1
  • Gateway mode: local loopback
  • Gateway auth: token
  • Channel tested: local TUI (openclaw-tui, gateway-client)

Expected behavior

A locally paired/operator-scoped TUI client should be able to call scope-gated RPCs such as:

  • status
  • system-presence
  • config.get

Actual behavior

Connection succeeds, but RPC calls fail with:

  • INVALID_REQUEST
  • missing scope: operator.read

openclaw gateway probe reports:

  • Connect: ok
  • RPC: limited - missing scope: operator.read

openclaw status --all reports:

  • Gateway ... unreachable (missing scope: operator.read)

Reproduction / troubleshooting already tried

Initial symptom

The gateway was running and healthy, but:

  • openclaw gateway probe
  • openclaw status --all

both reported missing scope: operator.read.

Device/pairing inspection

Local files showed device auth + pairing state, including:

  • ~/.openclaw/identity/device-auth.json
  • ~/.openclaw/devices/paired.json

At one point there was a mismatch where:

  • paired device scopes included operator.read
  • stored operator token scopes only showed operator.admin

Remediation steps attempted

  1. Rotated device token with explicit scopes:

    openclaw devices rotate --device <deviceId> --role operator \
      --scope operator.read \
      --scope operator.write \
      --scope operator.approvals \
      --scope operator.pairing \
      --scope operator.admin
  2. Verified token rotation succeeded.

  3. Updated local device auth state.

  4. Removed paired device and re-paired it.

  5. Restarted gateway cleanly:

    openclaw gateway restart
  6. Removed local device auth file entirely and let it regenerate:

    • backed up + removed ~/.openclaw/identity/device-auth.json
    • removed paired device
    • allowed fresh auto-pair on reconnect
  7. Launched TUI with explicit gateway token:

    TOKEN=$(python3 - <<'PY'
    import json, os
    p=os.path.expanduser("~/.openclaw/openclaw.json")
    with open(p) as f:
        print(json.load(f)["gateway"]["auth"]["token"])
    PY
    )
    openclaw tui --url ws://127.0.0.1:18789 --token "$TOKEN"

Observations

Freshly recreated local device auth shows full scopes

device-auth.json was recreated with operator scopes including:

  • operator.admin
  • operator.approvals
  • operator.pairing
  • operator.read
  • operator.write

Paired device table also shows full scopes

openclaw devices list --json shows the paired device with:

  • operator.read
  • operator.write
  • operator.approvals
  • operator.pairing
  • operator.admin

But runtime still rejects RPCs

Gateway logs continue to show:

  • status -> missing scope: operator.read
  • system-presence -> missing scope: operator.read
  • config.get -> missing scope: operator.read

Additional clue

One explicit-token TUI attempt produced:

  • unauthorized: gateway token mismatch

But after correcting token launch, successful connections still failed with missing scope: operator.read, so token mismatch does not fully explain the problem.

Relevant log snippets

Examples seen in gateway logs:

[ws] ⇄ res ✗ status 0ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ system-presence 0ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ config.get 0ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read

Earlier clue:

[gateway] security audit: device access upgrade requested reason=scope-upgrade ... scopesFrom=operator.read scopesTo=operator.admin client=gateway-client

And one token issue:

[ws] unauthorized ... client=openclaw-tui ui v2026.3.13 reason=token_mismatch

Suspected issue

This looks like a runtime auth/path mismatch or caching bug where:

  • device/token/pairing state on disk is correct,
  • but the active TUI/gateway-client session is authorized with an unexpected or stale effective scope set.

Possibly related to:

  • client identity differences (gateway-client / openclaw-tui vs cli)
  • token/device scope reconciliation
  • stale effective scopes after rotation/re-pair
  • auth path differences between implicit local device auth and explicit --token TUI connections

extent analysis

Fix Plan

To resolve the issue of missing operator.read scope, follow these steps:

  • Clear cache and stale data:
    • Remove ~/.openclaw/identity/device-auth.json and ~/.openclaw/devices/paired.json to ensure a clean start.
    • Restart the gateway: openclaw gateway restart
  • Re-pair device with correct scopes:
    • Rotate device token with explicit scopes:
      openclaw devices rotate --device <deviceId> --role operator \
        --scope operator.read \
        --scope operator.write \
        --scope operator.approvals \
        --scope operator.pairing \
        --scope operator.admin
    • Re-pair the device and verify the scopes are correctly applied.
  • Verify token and scope consistency:
    • Check the gateway logs for any errors or warnings related to token mismatches or scope issues.
    • Use the openclaw devices list --json command to verify the paired device has the correct scopes.
  • Update TUI connection:
    • Launch the TUI with the explicit gateway token:
      TOKEN=$(python3 - <<'PY'
      import json, os
      p=os.path.expanduser("~/.openclaw/openclaw.json")
      with open(p) as f:
          print(json.load(f)["gateway"]["auth"]["token"])
      PY
      )
      openclaw tui --url ws://127.0.0.1:18789 --token "$TOKEN"
    • Verify the TUI connection is successful and the operator.read scope is recognized.

Verification

To verify the fix, run the following commands:

  • openclaw gateway probe should report Connect: ok and RPC: ok.
  • openclaw status --all should report the gateway as reachable without any scope errors.
  • Attempt to call scope-gated RPCs such as status, system-presence, and config.get to ensure they succeed without missing scope: operator.read errors.

Extra Tips

  • Regularly review and update device tokens and scopes to ensure consistency and security.
  • Monitor gateway logs for any errors or warnings related to token mismatches or scope issues.
  • Consider implementing automated scripts to rotate device tokens and verify scope consistency.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

A locally paired/operator-scoped TUI client should be able to call scope-gated RPCs such as:

  • status
  • system-presence
  • config.get

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING