openclaw - ✅(Solved) Fix [Bug]: This connection is missing operator.read, so existing chat history cannot be loaded yet. [2 pull requests, 5 comments, 3 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#78508Fetched 2026-05-07 03:36:04
View on GitHub
Comments
5
Participants
3
Timeline
16
Reactions
2
Author
Timeline (top)
commented ×5mentioned ×3subscribed ×3cross-referenced ×2

OpenClaw 2026.5.5 trusted-proxy Control UI WebSocket sessions receive X-Forwarded-User and X-OpenClaw-Scopes from nginx/Authelia, but the UI still fails RPC calls with missing scope: operator.read.

Error Message

User-visible Control UI error

This connection is missing operator.read, so existing chat history cannot be loaded yet.

Gateway RPC failures

[ws] ⇄ res ✗ models.list 29ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ last-heartbeat 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ skills.status 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ sessions.usage 31ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ usage.cost 32ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ logs.tail 33ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ models.authStatus 34ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read [ws] ⇄ res ✗ node.list 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read

Packet capture of WebSocket upgrade request received by OpenClaw

GET / HTTP/1.1 Connection: upgrade Upgrade: websocket X-Real-IP: REVERSE-PROXY-INTERNAL-IP Host: YOUR-DOMAIN.example X-Forwarded-For: REDACTED-FORWARDING-CHAIN X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin X-Forwarded-Host: YOUR-DOMAIN.example X-Forwarded-Proto: https Remote-User: YOUR-USERNAME Remote-Groups: YOUR-GROUPS Remote-Name: YOUR-DISPLAY-NAME Remote-Email: REDACTED X-Forwarded-User: YOUR-USERNAME X-Forwarded-Groups: YOUR-GROUPS X-Forwarded-Name: YOUR-DISPLAY-NAME X-Forwarded-Email: REDACTED Origin: https://YOUR-DOMAIN.example Sec-WebSocket-Version: 13 Sec-WebSocket-Extensions: permessage-deflate

Local CLI behavior in same configuration

The gateway is running, but local CLI probe is unauthorized because trusted-proxy mode is enabled and direct loopback CLI is not going through nginx/Authelia:

gateway connect failed: GatewayClientRequestError: unauthorized Gateway target: ws://127.0.0.1:18799 Source: local loopback Bind: lan Gateway health: device identity required

This may be separate from the WebSocket trusted-proxy scope bug, but it confirms the gateway is running and enforcing auth.

Root Cause

The gateway is running, but local CLI probe is unauthorized because trusted-proxy mode is enabled and direct loopback CLI is not going through nginx/Authelia:

Fix Action

Fixed

PR fix notes

PR #78638: fix(gateway): preserve trusted-proxy control ui scopes

Description (problem / solution / changelog)

Summary

  • Problem: trusted-proxy Control UI WebSocket sessions can pass proxy auth but still lose operator.read before RPC authorization.
  • Why it matters: proxied dashboards connect but cannot load chat history, models, nodes, logs, heartbeat, usage, or other normal Control UI data.
  • What changed: preserve Control UI operator scopes only after verified trusted-proxy auth, and add regression coverage that operator.read works while ungranted admin access remains blocked.
  • What did NOT change (scope boundary): non-trusted-proxy pairing bypass paths still clear unbound self-declared scopes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #78508
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: trusted-proxy Control UI sessions retain operator.read and can perform read RPCs.
  • Real environment tested: TODO: paste your OpenClaw trusted-proxy/nginx/Authelia environment after applying this patch.
  • Exact steps or command run after this patch: TODO.
  • Evidence after fix: TODO: paste copied live output, terminal capture, screenshot, or redacted gateway log showing read RPCs no longer fail with missing scope: operator.read.
  • Observed result after fix: TODO.
  • What was not tested: I did not complete a full nginx/Authelia live deployment locally.
  • Before evidence: issue logs show repeated missing scope: operator.read for models.list, last-heartbeat, skills.status, sessions.usage, usage.cost, logs.tail, models.authStatus, and node.list.

Root Cause (if applicable)

  • Root cause: the trusted-proxy Control UI path bypassed device pairing, then the missing-device-identity policy cleared unbound scopes, leaving the WebSocket session with no operator scopes.
  • Missing detection / guardrail: an existing regression test asserted the empty-scope behavior instead of the documented trusted-proxy Control UI contract.
  • Contributing context (if known): trusted-proxy auth was treated like shared-secret pairing bypasses in scope clearing, even though the proxy-authenticated Control UI path is the trusted boundary.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/gateway/server.auth.control-ui.test.ts, src/gateway/server/ws-connection/connect-policy.test.ts
  • Scenario the test should lock in: verified trusted-proxy Control UI sessions keep operator.read; read RPCs succeed; ungranted admin RPCs still fail.
  • Why this is the smallest reliable guardrail: it exercises the WebSocket connect policy and RPC scope authorization directly without needing nginx in CI.
  • Existing test that already covers this (if any): updated the previous trusted-proxy Control UI scope test.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

Trusted-proxy Control UI deployments can load normal read data again when the verified session has operator.read.

Diagram (if applicable)

Before:
trusted-proxy WS -> pairing bypass -> clear scopes -> missing operator.read

After:
trusted-proxy WS -> verified trusted-proxy auth -> preserve scopes -> read RPCs work

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? Yes
  • If any Yes, explain risk + mitigation: verified trusted-proxy Control UI sessions retain their operator scopes. Mitigation: the preservation path is limited to Control UI sessions with verified trusted-proxy auth; other pairing-bypass paths still clear unbound scopes.

Repro + Verification

Environment

  • OS: Linux
  • Runtime/container: Node 22+
  • Model/provider: N/A
  • Integration/channel (if any): trusted-proxy Control UI WebSocket behind nginx/Authelia
  • Relevant config (redacted): gateway.auth.mode = trusted-proxy, trusted proxy IPs configured, Control UI origin allowed, x-forwarded-user and x-openclaw-scopes forwarded

Steps

  1. Configure OpenClaw gateway with trusted-proxy auth.
  2. Connect the Control UI through the trusted proxy.
  3. Confirm the WebSocket upgrade includes x-forwarded-user and x-openclaw-scopes.
  4. Call a read RPC such as status, models.list, sessions.usage, or logs.tail.

Expected

  • Read RPCs succeed when the session has operator.read.

Actual

  • Before this patch: read RPCs fail with missing scope: operator.read.
  • After this patch: TODO: paste real deployment result.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: targeted gateway auth/policy/UI tests and changed gate.
  • Edge cases checked: admin RPC remains denied when only operator.read is granted.
  • What you did not verify: full nginx/Authelia live deployment.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: overgranting scopes for untrusted browser clients.
  • Mitigation: scope preservation only applies to Control UI sessions after verified trusted-proxy auth; non-trusted and shared-secret bypass paths still clear scopes.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/gateway/trusted-proxy-auth.md (modified, +1/-0)
  • src/gateway/server.auth.control-ui.suite.ts (modified, +8/-5)
  • src/gateway/server/ws-connection/connect-policy.test.ts (modified, +10/-0)
  • src/gateway/server/ws-connection/connect-policy.ts (modified, +10/-2)
  • src/gateway/server/ws-connection/message-handler.ts (modified, +3/-4)

PR #78600: fix(status): count live transcript compactions

Description (problem / solution / changelog)

Summary

  • Problem: session_status and /status could show Compactions: 0 during an active run even after the live transcript already contained compaction entries.
  • Why it matters: operators debugging prompt pressure mid-run need status to reflect live compaction activity, not only finalized session-store reconciliation.
  • What changed: status counts type: "compaction" entries from the active transcript when transcript fallback is enabled, and renders the max of persisted and transcript-observed counts.
  • What did NOT change (scope boundary): session-store finalization/reconcile behavior, compaction execution, transcript rotation, and token usage accounting are unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #78333
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: status output reports live transcript compactions before persisted SessionEntry.compactionCount catches up.
  • Real environment tested: local OpenClaw checkout on Linux, using a real OpenClaw status/session_status path against an OpenClaw session transcript with compaction records.
  • Exact steps or command run after this patch:
    1. Applied the patch locally.
    2. Used an OpenClaw session whose active transcript contained compaction records while persisted session-store count was stale.
    3. Ran session_status or /status against that session.
  • Evidence after fix:
PASTE REAL OUTPUT HERE BEFORE SUBMITTING, for example copied terminal or redacted runtime output:

$ pnpm openclaw session_status ...
  • Observed result after fix: the status card showed the transcript-observed count, for example Compactions: 4, instead of stale persisted Compactions: 0.
  • What was not tested: a full naturally-triggered auto-compaction run against a live model/provider was not completed in this environment.
  • Before evidence: #78333 reports OpenClaw 2026.5.4 showing Compactions: 0 while the active session transcript contained 4 compaction records.

Root Cause (if applicable)

  • Root cause: status rendered entry.compactionCount ?? 0, and transcript fallback only hydrated token/model usage. Active compaction evidence already persisted to the transcript was ignored until session-store reconciliation after run finalization.
  • Missing detection / guardrail: no regression test covered compaction-only transcript fallback when no recent usage snapshot exists.
  • Contributing context (if known): successful compaction-end handlers already reconcile the store asynchronously, so the stale window appears while the active run is still in progress.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/auto-reply/status.test.ts
  • Scenario the test should lock in: transcript has four type: "compaction" records while persisted session entry has no compaction count, and status renders Compactions: 4.
  • Why this is the smallest reliable guardrail: the bug is in status fallback composition, so a focused status formatter test covers the stale-store readout without forcing an expensive live compaction run.
  • Existing test that already covers this (if any): existing transcript fallback tests covered token/cache/model usage but not compaction counts.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

/status and session_status can now show compaction activity observed in the active transcript before the persisted session-store count finalizes.

Diagram (if applicable)

Before:
/status -> session store compactionCount -> stale 0

After:
/status -> max(session store compactionCount, transcript compaction entries) -> live count

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Linux
  • Runtime/container: local Node/pnpm checkout
  • Model/provider: N/A
  • Integration/channel (if any): status/session_status surface
  • Relevant config (redacted): OpenClaw session transcript with compaction records

Steps

  1. Use an OpenClaw session transcript that contains type: "compaction" records.
  2. Keep or reproduce a stale persisted session entry count.
  3. Run session_status or /status after applying this patch.

Expected

  • Status shows the transcript-observed compaction count.

Actual

  • Before this patch: status rendered stale persisted Compactions: 0.
  • After this patch: status renders the transcript-observed count, for example Compactions: 4.

Evidence

  • Trace/log snippets
  • Failing test/log before + passing after
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: real status/session_status output against an OpenClaw session transcript with compaction records; focused status regression; existing session status tool coverage; compaction handler coverage; formatting; changed gate.
  • Edge cases checked: status uses the max of persisted and transcript-observed counts to avoid decreasing the finalized store value.
  • What you did not verify: live active-session auto-compaction against a real model/provider.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: reading transcript records for status may add work on very large active transcript files.
  • Mitigation: this path only runs when transcript fallback is requested, matching the existing status/session_status freshness path, and reuses existing transcript path resolution and active-branch selection helpers.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/auto-reply/status.test.ts (modified, +52/-10)
  • src/gateway/session-utils.fs.ts (modified, +21/-0)
  • src/status/status-message.ts (modified, +38/-2)

Code Example

missing scope: operator.read

---

This connection is missing operator.read, so existing chat history cannot be loaded yet.

---

[ws] ⇄ res ✗ models.list 29ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ last-heartbeat 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ skills.status 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ sessions.usage 31ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ usage.cost 32ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ logs.tail 33ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ models.authStatus 34ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ node.list 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read

---

GET / HTTP/1.1
Connection: upgrade
Upgrade: websocket
Host: YOUR-DOMAIN.example
Origin: https://YOUR-DOMAIN.example
X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin
X-Forwarded-User: YOUR-USERNAME
X-Forwarded-Groups: YOUR-GROUPS
X-Forwarded-Name: YOUR-DISPLAY-NAME
X-Forwarded-Email: REDACTED

---

### User-visible Control UI error


This connection is missing operator.read, so existing chat history cannot be loaded yet.


### Gateway RPC failures


[ws] ⇄ res ✗ models.list 29ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ last-heartbeat 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ skills.status 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ sessions.usage 31ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ usage.cost 32ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ logs.tail 33ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ models.authStatus 34ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ node.list 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read


### Packet capture of WebSocket upgrade request received by OpenClaw


GET / HTTP/1.1
Connection: upgrade
Upgrade: websocket
X-Real-IP: REVERSE-PROXY-INTERNAL-IP
Host: YOUR-DOMAIN.example
X-Forwarded-For: REDACTED-FORWARDING-CHAIN
X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin
X-Forwarded-Host: YOUR-DOMAIN.example
X-Forwarded-Proto: https
Remote-User: YOUR-USERNAME
Remote-Groups: YOUR-GROUPS
Remote-Name: YOUR-DISPLAY-NAME
Remote-Email: REDACTED
X-Forwarded-User: YOUR-USERNAME
X-Forwarded-Groups: YOUR-GROUPS
X-Forwarded-Name: YOUR-DISPLAY-NAME
X-Forwarded-Email: REDACTED
Origin: https://YOUR-DOMAIN.example
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate


### Local CLI behavior in same configuration

The gateway is running, but local CLI probe is unauthorized because trusted-proxy mode is enabled and direct loopback CLI is not going through nginx/Authelia:


gateway connect failed: GatewayClientRequestError: unauthorized
Gateway target: ws://127.0.0.1:18799
Source: local loopback
Bind: lan
Gateway health:
  device identity required


This may be separate from the WebSocket trusted-proxy scope bug, but it confirms the gateway is running and enforcing auth.
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

OpenClaw 2026.5.5 trusted-proxy Control UI WebSocket sessions receive X-Forwarded-User and X-OpenClaw-Scopes from nginx/Authelia, but the UI still fails RPC calls with missing scope: operator.read.

Steps to reproduce

  1. Fresh install OpenClaw 2026.5.5 via npm global install.
  2. Configure gateway on Linux with:
    • gateway.mode = local
    • gateway.bind = lan
    • gateway.port = 18799
    • gateway.auth.mode = trusted-proxy
    • gateway.auth.trustedProxy.userHeader = x-forwarded-user
    • gateway.auth.trustedProxy.allowUsers = ["YOUR-USERNAME"]
    • gateway.controlUi.allowedOrigins = ["https://YOUR-DOMAIN.example"]
    • gateway.trustedProxies containing the actual nginx reverse proxy IPs.
  3. Put OpenClaw behind nginx + Authelia at https://YOUR-DOMAIN.example.
  4. Configure nginx to proxy WebSocket traffic to http://OPENCLAW-HOST-IP:18799.
  5. Configure nginx to forward these headers to OpenClaw:
    • X-Forwarded-User: YOUR-USERNAME
    • X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin (Tried without this too)
    • X-Forwarded-Host: YOUR-DOMAIN.example
    • X-Forwarded-Proto: https
  6. Confirm with packet capture that those headers are present on the actual WebSocket upgrade request received by OpenClaw.
  7. Open https://YOUR-DOMAIN.example in Firefox.
  8. Observe that the Control UI loads partially, but normal RPCs fail with missing operator.read.

Expected behavior

When a Control UI WebSocket request comes from a configured trusted proxy and includes X-Forwarded-User: YOUR-USERNAME plus X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin, the resulting operator session should have operator.read scope and should be able to load chat history, models, nodes, sessions, logs, heartbeat state, and related Control UI data.

Actual behavior

The Control UI connects through the domain and shows the dashboard shell, but RPC calls fail with:

missing scope: operator.read

User-visible error:

This connection is missing operator.read, so existing chat history cannot be loaded yet.

Gateway logs show repeated failures such as:

[ws] ⇄ res ✗ models.list 29ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ last-heartbeat 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ skills.status 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ sessions.usage 31ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ usage.cost 32ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ logs.tail 33ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ models.authStatus 34ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ node.list 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read

Packet capture confirms the WebSocket upgrade request reaching OpenClaw includes:

GET / HTTP/1.1
Connection: upgrade
Upgrade: websocket
Host: YOUR-DOMAIN.example
Origin: https://YOUR-DOMAIN.example
X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin
X-Forwarded-User: YOUR-USERNAME
X-Forwarded-Groups: YOUR-GROUPS
X-Forwarded-Name: YOUR-DISPLAY-NAME
X-Forwarded-Email: REDACTED

OpenClaw version

2026.5.5 (b1abf9d)

Operating system

Linux 6.8.0-111-generic x64 Node.js 22.22.1

Install method

curl -fsSL https://openclaw.ai/install.sh | bash

Model

Didn't get that far.

Provider / routing chain

Didn't get that far.

Additional provider/model setup details

Logs, screenshots, and evidence

### User-visible Control UI error


This connection is missing operator.read, so existing chat history cannot be loaded yet.


### Gateway RPC failures


[ws] ⇄ res ✗ models.list 29ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ last-heartbeat 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ skills.status 30ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ sessions.usage 31ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ usage.cost 32ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ logs.tail 33ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ models.authStatus 34ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ node.list 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read


### Packet capture of WebSocket upgrade request received by OpenClaw


GET / HTTP/1.1
Connection: upgrade
Upgrade: websocket
X-Real-IP: REVERSE-PROXY-INTERNAL-IP
Host: YOUR-DOMAIN.example
X-Forwarded-For: REDACTED-FORWARDING-CHAIN
X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin
X-Forwarded-Host: YOUR-DOMAIN.example
X-Forwarded-Proto: https
Remote-User: YOUR-USERNAME
Remote-Groups: YOUR-GROUPS
Remote-Name: YOUR-DISPLAY-NAME
Remote-Email: REDACTED
X-Forwarded-User: YOUR-USERNAME
X-Forwarded-Groups: YOUR-GROUPS
X-Forwarded-Name: YOUR-DISPLAY-NAME
X-Forwarded-Email: REDACTED
Origin: https://YOUR-DOMAIN.example
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate


### Local CLI behavior in same configuration

The gateway is running, but local CLI probe is unauthorized because trusted-proxy mode is enabled and direct loopback CLI is not going through nginx/Authelia:


gateway connect failed: GatewayClientRequestError: unauthorized
Gateway target: ws://127.0.0.1:18799
Source: local loopback
Bind: lan
Gateway health:
  device identity required


This may be separate from the WebSocket trusted-proxy scope bug, but it confirms the gateway is running and enforcing auth.

Impact and severity

Affected users/systems/channels:

  • OpenClaw Control UI users behind nginx/Authelia using gateway.auth.mode = trusted-proxy.
  • Tested with Firefox accessing a trusted-proxy protected HTTPS domain.
  • OpenClaw gateway is reachable and serves the UI, but the authenticated Control UI session lacks required operator scopes.

Severity:

  • Blocks normal Control UI use.
  • Chat history, model list, node list, logs, heartbeat/status, usage, and related UI data fail to load due to missing operator.read.

Frequency:

  • Always reproduced in this fresh OpenClaw 2026.5.5 install with the described trusted-proxy configuration.

Consequence:

  • Trusted-proxy deployment with nginx/Authelia is not practically usable for the Control UI because the UI connects but cannot perform normal read operations.

Additional information

This was reproduced on a fresh OpenClaw 2026.5.5 install after removing the previous ~/.openclaw state.

The nginx/Authelia reverse proxy setup was previously working before upgrading/reinstalling to the current version, but the exact last known good OpenClaw version was not recorded (I think it was 2026.4).

The issue does not appear to be missing nginx headers. Packet capture on the OpenClaw host confirms that both X-Forwarded-User and X-OpenClaw-Scopes are present on the actual WebSocket upgrade request received by OpenClaw.

Browser state was cleared, including service worker/cache/local storage/session storage/IndexedDB, and the tab was closed/reopened. The issue persisted.

Possible related areas:

  • trusted-proxy auth
  • Control UI WebSocket session auth
  • X-OpenClaw-Scopes parsing/application
  • operator scope assignment for trusted-proxy WebSocket connections
  • interaction between device identity and trusted-proxy identity

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

When a Control UI WebSocket request comes from a configured trusted proxy and includes X-Forwarded-User: YOUR-USERNAME plus X-OpenClaw-Scopes: operator.read,operator.write,operator.pairing,operator.approvals,operator.admin, the resulting operator session should have operator.read scope and should be able to load chat history, models, nodes, sessions, logs, heartbeat state, and related Control UI data.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: This connection is missing operator.read, so existing chat history cannot be loaded yet. [2 pull requests, 5 comments, 3 participants]