openclaw - 💡(How to fix) Fix v2026.4.24: Plugin synthetic operator client lacks `operator.admin` scope, breaking `subagent.deleteSession` for memory-core dreaming narrative cleanup [2 comments, 2 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#74332Fetched 2026-04-30 06:25:24
View on GitHub
Comments
2
Participants
2
Timeline
3
Reactions
2
Author
Timeline (top)
commented ×2closed ×1

The plugin synthetic operator client created by server-plugin-bootstrap defaults to the scope set ["operator.write"]. Several first-party gateway methods that plugins invoke through dispatchGatewayMethod — including sessions.delete, sessions.reset, sessions.patch, and sessions.compact — require operator.admin per the ADMIN_SCOPE table in method-scopes-B1c_GUbd.js. The mismatch is silent: the call is rejected at scope-check time with missing scope: operator.admin, the failure is logged at WARN, and the calling plugin's flow continues without the cleanup the call was meant to perform.

The most visible victim is memory-core's dreaming narrative cleanup. After every narrative phase (light / deep / rem), dreaming-narrative-BKXbhYcL.js calls params.subagent.deleteSession({ sessionKey }) to release the ephemeral narrative session. That call goes through the same synthetic operator client, hits the scope ceiling, and silently fails. Three WARN lines per nightly run accumulate in /tmp/openclaw/openclaw-<date>.log, and dangling narrative sessions accumulate under ~/.openclaw/agents/orchestrator/sessions/__dreaming_*__:*.

The same scope ceiling also breaks the subagent.run call that generates the narrative content for a phase: when the narrative subagent itself tries to write to a session it doesn't own, the underlying sessions.patch is denied, and the subagent run times out with no narrative diary entry produced. On this host that manifested as narrative generation ended with status=timeout for {light,deep,rem} phase and DREAMS.md going un-updated for the affected runs.

Error Message

The plugin synthetic operator client created by server-plugin-bootstrap defaults to the scope set ["operator.write"]. Several first-party gateway methods that plugins invoke through dispatchGatewayMethod — including sessions.delete, sessions.reset, sessions.patch, and sessions.compact — require operator.admin per the ADMIN_SCOPE table in method-scopes-B1c_GUbd.js. The mismatch is silent: the call is rejected at scope-check time with missing scope: operator.admin, the failure is logged at WARN, and the calling plugin's flow continues without the cleanup the call was meant to perform. The most visible victim is memory-core's dreaming narrative cleanup. After every narrative phase (light / deep / rem), dreaming-narrative-BKXbhYcL.js calls params.subagent.deleteSession({ sessionKey }) to release the ephemeral narrative session. That call goes through the same synthetic operator client, hits the scope ceiling, and silently fails. Three WARN lines per nightly run accumulate in /tmp/openclaw/openclaw-<date>.log, and dangling narrative sessions accumulate under ~/.openclaw/agents/orchestrator/sessions/__dreaming_*__:*. 4. After the cron run, three WARN lines appear, one per phase: 2026-04-29T03:03:11.891+07:00 WARN memory-core: narrative generation ended with status=timeout for light phase. 2026-04-29T03:03:22.914+07:00 WARN memory-core: narrative generation ended with status=timeout for rem phase.

Root Cause

The patch must be re-applied after every openclaw@<version> upgrade because npm replaces the bundled file.

Fix Action

Workaround

One-line patch on the bundled binary, reversible:

sudo cp /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js.bak-pre-2026-04-29

sudo sed -i 's/scopes: params?\.scopes ?? \["operator\.write"\]/scopes: params?.scopes ?? ["operator.write", "operator.admin"]/' \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js

sudo systemctl restart openclaw

Verify by waiting for the next dreaming cron run and confirming the three narrative session cleanup failed … missing scope: operator.admin warnings no longer appear.

The patch must be re-applied after every openclaw@<version> upgrade because npm replaces the bundled file.

Code Example

memory-core: narrative session cleanup failed for light phase: missing scope: operator.admin
   memory-core: narrative session cleanup failed for deep phase: missing scope: operator.admin
   memory-core: narrative session cleanup failed for rem phase: missing scope: operator.admin

---

scopes: params?.scopes ?? ["operator.write"]

---

return dispatchGatewayMethod("sessions.delete", { sessionKey });

---

$ grep -n 'scopes: params?\.scopes ?? \["operator\.write"\]' /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js
  10835:        scopes: params?.scopes ?? ["operator.write"],

---

2026-04-29T03:03:11.891+07:00 WARN  memory-core: narrative generation ended with status=timeout for light phase.
  2026-04-29T03:03:22.914+07:00 WARN  memory-core: narrative generation ended with status=timeout for rem phase.

---

sudo cp /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js.bak-pre-2026-04-29

sudo sed -i 's/scopes: params?\.scopes ?? \["operator\.write"\]/scopes: params?.scopes ?? ["operator.write", "operator.admin"]/' \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js

sudo systemctl restart openclaw
RAW_BUFFERClick to expand / collapse

Summary

The plugin synthetic operator client created by server-plugin-bootstrap defaults to the scope set ["operator.write"]. Several first-party gateway methods that plugins invoke through dispatchGatewayMethod — including sessions.delete, sessions.reset, sessions.patch, and sessions.compact — require operator.admin per the ADMIN_SCOPE table in method-scopes-B1c_GUbd.js. The mismatch is silent: the call is rejected at scope-check time with missing scope: operator.admin, the failure is logged at WARN, and the calling plugin's flow continues without the cleanup the call was meant to perform.

The most visible victim is memory-core's dreaming narrative cleanup. After every narrative phase (light / deep / rem), dreaming-narrative-BKXbhYcL.js calls params.subagent.deleteSession({ sessionKey }) to release the ephemeral narrative session. That call goes through the same synthetic operator client, hits the scope ceiling, and silently fails. Three WARN lines per nightly run accumulate in /tmp/openclaw/openclaw-<date>.log, and dangling narrative sessions accumulate under ~/.openclaw/agents/orchestrator/sessions/__dreaming_*__:*.

The same scope ceiling also breaks the subagent.run call that generates the narrative content for a phase: when the narrative subagent itself tries to write to a session it doesn't own, the underlying sessions.patch is denied, and the subagent run times out with no narrative diary entry produced. On this host that manifested as narrative generation ended with status=timeout for {light,deep,rem} phase and DREAMS.md going un-updated for the affected runs.

Environment

  • OpenClaw: 2026.4.24 (cbcfdf6), installed via sudo npm install -g [email protected].
  • Node: 22.22.2.
  • OS: Linux 6.8.0-106-generic.
  • Plugins enabled: memory-core, memory-wiki, telegram, plus stock defaults. memory-core.config.dreaming.enabled: true, frequency: "0 3 * * *", timezone: "Asia/Jakarta".
  • 5 agents (orchestrator, reasoner, coder, fast, multimodal). The dreaming flow runs against the orchestrator workspace.

Steps to reproduce

  1. On v2026.4.24, configure any agent with memory-core enabled and dreaming.enabled: true.
  2. Wait for the daily managed dreaming cron to fire (default 0 3 * * *).
  3. Tail the active gateway log: tail -F /tmp/openclaw/openclaw-$(date +%F).log. The active path is announced at startup as [gateway] log file: /tmp/openclaw/openclaw-<date>.log.
  4. After the cron run, three WARN lines appear, one per phase:
    memory-core: narrative session cleanup failed for light phase: missing scope: operator.admin
    memory-core: narrative session cleanup failed for deep phase: missing scope: operator.admin
    memory-core: narrative session cleanup failed for rem phase: missing scope: operator.admin
  5. List the orchestrator session directory: ls ~/.openclaw/agents/orchestrator/sessions/ | grep __dreaming — entries from prior runs accumulate (cleanup never happened).

Expected behavior

subagent.deleteSession invoked by a plugin should successfully release the ephemeral session it created. Either:

  • the synthetic operator client is granted whatever scopes the methods plugins legitimately need (including operator.admin for sessions.delete/reset/patch/compact), or
  • subagent.deleteSession widens its own dispatch with syntheticScopes: ["operator.write", "operator.admin"] since the caller can't override it.

Either way, no missing scope warning should appear in the dreaming flow's normal path.

Actual behavior

server-plugin-bootstrap-DBjRPg3N.js:10835 creates the synthetic operator client with:

scopes: params?.scopes ?? ["operator.write"]

subagent.deleteSession (in the same file, around the dispatchGatewayMethod definition) calls without an options arg, so the caller cannot upgrade scopes:

return dispatchGatewayMethod("sessions.delete", { sessionKey });

method-scopes-B1c_GUbd.js's ADMIN_SCOPE set lists sessions.delete, sessions.reset, sessions.patch, sessions.compact, and others. The dispatch is rejected at scope-check time, surfaces as missing scope: operator.admin, and the caller's promise resolves to a non-throwing failure that the dreaming pipeline logs but does not propagate.

A second-order effect: subagent.run for narrative-generation also dispatches through the same synthetic-scoped client, and sessions.patch is in ADMIN_SCOPE. The narrative subagent fails to persist, the run times out, and no DREAMS.md entry is written for that phase.

Diagnostic evidence

  • Scope default: single occurrence at line 10835.
    $ grep -n 'scopes: params?\.scopes ?? \["operator\.write"\]' /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js
    10835:        scopes: params?.scopes ?? ["operator.write"],
  • Method scope table: /usr/lib/node_modules/openclaw/dist/method-scopes-B1c_GUbd.js. ADMIN_SCOPE includes sessions.delete, sessions.reset, sessions.patch, sessions.compact, and the cron-mutation methods.
  • Plugin call sites that hit this:
    • dreaming-narrative-BKXbhYcL.js: params.subagent.deleteSession({ sessionKey }) per phase.
    • dreaming-DugQEpYx.js: narrative subagent runs that internally sessions.patch.
  • Log evidence (this host, 2026-04-29 03:03 WIB):
    2026-04-29T03:03:11.891+07:00 WARN  memory-core: narrative generation ended with status=timeout for light phase.
    2026-04-29T03:03:22.914+07:00 WARN  memory-core: narrative generation ended with status=timeout for rem phase.
    with matching scope-rejection warnings emitted alongside.

Workaround

One-line patch on the bundled binary, reversible:

sudo cp /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js.bak-pre-2026-04-29

sudo sed -i 's/scopes: params?\.scopes ?? \["operator\.write"\]/scopes: params?.scopes ?? ["operator.write", "operator.admin"]/' \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js

sudo systemctl restart openclaw

Verify by waiting for the next dreaming cron run and confirming the three narrative session cleanup failed … missing scope: operator.admin warnings no longer appear.

The patch must be re-applied after every openclaw@<version> upgrade because npm replaces the bundled file.

Suggested fix

Two clean options, in order of decreasing surface area:

  1. Widen the synthetic operator client default to include operator.admin (the one-line change above). Plugins are first-party and already trusted with dispatchGatewayMethod; the scope distinction between write and admin does not meaningfully gate them from anything they couldn't already reach via filesystem mutation.

  2. Have subagent.deleteSession (and the other affected helpers) opt-in to admin scope at the call site by passing { syntheticScopes: ["operator.write", "operator.admin"] } to dispatchGatewayMethod. Narrower blast radius, but you have to find every call site — at minimum subagent.deleteSession, subagent.resetSession, and the sessions.patch calls inside the narrative subagent flow.

Option 1 is what I applied as a workaround. Option 2 is what I'd ship if I were maintaining the plugin runtime.

Severity

Medium. Cosmetic noise in logs, but two real consequences:

  • Dreaming narrative diary entries silently fail to land in DREAMS.md whenever the narrative subagent's sessions.patch is denied.
  • Orphan dreaming sessions accumulate under ~/.openclaw/agents/orchestrator/sessions/__dreaming_*__:* because cleanup never runs. Long-running deployments will see hundreds of entries over weeks.

Nothing crashes, nothing user-visible breaks immediately, and the workaround is a single sed line — hence medium rather than high.

extent analysis

TL;DR

The most likely fix is to widen the synthetic operator client default to include operator.admin scope.

Guidance

  • Identify the line in server-plugin-bootstrap-DBjRPg3N.js where the synthetic operator client is created with the default scope ["operator.write"].
  • Update this line to include operator.admin in the default scope, as shown in the provided one-line patch.
  • Restart the OpenClaw service to apply the changes.
  • Verify the fix by waiting for the next dreaming cron run and checking that the missing scope: operator.admin warnings no longer appear in the logs.

Example

The one-line patch provided in the issue can be used as a temporary workaround:

sudo sed -i 's/scopes: params?\.scopes ?? \["operator\.write"\]/scopes: params?.scopes ?? ["operator.write", "operator.admin"]/' \
        /usr/lib/node_modules/openclaw/dist/server-plugin-bootstrap-DBjRPg3N.js

Notes

This fix may need to be reapplied after every OpenClaw upgrade, as the bundled file may be replaced.

Recommendation

Apply the workaround by updating the synthetic operator client default scope to include operator.admin, as it is a simple and effective solution to the issue.

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

subagent.deleteSession invoked by a plugin should successfully release the ephemeral session it created. Either:

  • the synthetic operator client is granted whatever scopes the methods plugins legitimately need (including operator.admin for sessions.delete/reset/patch/compact), or
  • subagent.deleteSession widens its own dispatch with syntheticScopes: ["operator.write", "operator.admin"] since the caller can't override it.

Either way, no missing scope warning should appear in the dreaming flow's normal path.

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 - 💡(How to fix) Fix v2026.4.24: Plugin synthetic operator client lacks `operator.admin` scope, breaking `subagent.deleteSession` for memory-core dreaming narrative cleanup [2 comments, 2 participants]