openclaw - 💡(How to fix) Fix memory-core dreaming cleanup fails: subagent deleteSession cannot dispatch sessions.delete (operator.admin required) [1 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#72712Fetched 2026-04-28 06:33:07
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2marked_as_duplicate ×2closed ×1commented ×1

Error Message

the error — but this is not a correct upstream change because it removes the

Root Cause

For self-hosted users hitting this on every dreaming run, a local patch to the distributed dist/server-plugin-bootstrap-*.js to pass { syntheticScopes: ["operator.admin"] } from deleteSession will silence the error — but this is not a correct upstream change because it removes the security boundary asserted by the test above.

Fix Action

Workaround

For self-hosted users hitting this on every dreaming run, a local patch to the distributed dist/server-plugin-bootstrap-*.js to pass { syntheticScopes: ["operator.admin"] } from deleteSession will silence the error — but this is not a correct upstream change because it removes the security boundary asserted by the test above.

Code Example

[memory-core/dreaming] failed to delete dreaming subagent session: missing scope: operator.admin

---

async deleteSession(params) {
  await dispatchGatewayMethod("sessions.delete", {
    key: params.sessionKey,
    deleteTranscript: params.deleteTranscript ?? true,
  });
},
RAW_BUFFERClick to expand / collapse

Symptom

When the memory-core dreaming pipeline finishes a narrative cycle (cron-driven or manual), session cleanup fails with:

[memory-core/dreaming] failed to delete dreaming subagent session: missing scope: operator.admin

This recurs on every dreaming run. The narrative completes (memories are written) but the ephemeral subagent session is never reaped, leaving stale session records.

Environment

  • openclaw 2026.4.24 (also reproduced against current main, commit 0286bb98)
  • Linux / WSL Ubuntu-24.04, Node 22
  • Plugins enabled: active-memory, browser, memory-core, memory-wiki, whatsapp
  • Cron-driven dreaming (memory.dreaming.* jobs registered via cron)
  • Reproduces with default cron.enabled: true

Trace

The dreaming worker calls subagent.deleteSession(...) on the plugin runtime. That hits createGatewaySubagentRuntime().deleteSession in src/gateway/server-plugins.ts (≈ line 380):

async deleteSession(params) {
  await dispatchGatewayMethod("sessions.delete", {
    key: params.sessionKey,
    deleteTranscript: params.deleteTranscript ?? true,
  });
},

dispatchGatewayMethod looks up a request scope via getPluginRuntimeGatewayRequestScope(). When the dreaming job is invoked from the cron service / fallback gateway context (not a live operator request), no scope is set, so dispatchGatewayMethod falls back to createSyntheticOperatorClient() which mints a client with scopes: [WRITE_SCOPE].

But sessions.delete is in the ADMIN_SCOPE list (src/gateway/method-scopes.ts ≈ line 175), so authorization fails with missing scope: operator.admin.

The existing test asserts this is the intentional behavior:

src/gateway/server-plugins.test.ts test("rejects fallback session deletion without minting admin scope", …) …rejects.toThrow("missing scope: operator.admin")

So the gateway side is by design. The contract is: a caller wanting to delete a session must already be in a withPluginRuntimeGatewayRequestScope whose client carries operator.admin (the second test, "allows session deletion when the request scope already has admin", confirms this works).

Where the contract is broken

The memory-core dreaming worker (bundled plugin) fires its cleanup from a cron callback. It does not appear to wrap the cleanup in withPluginRuntimeGatewayRequestScope with an admin client, so it inevitably hits the synthetic operator.write fallback and is rejected.

Possible fixes (need maintainer guidance — not opening a PR yet)

  1. Memory-core side: wrap dreaming cleanups in withPluginRuntimeGatewayRequestScope with an admin-scoped synthetic client. Memory-core is a trusted bundled plugin, so this is reasonable — but the wrapping helper isn't currently exposed to plugin code.

  2. Plugin runtime side: introduce an opt-in subagent.deleteSession({ asAdmin: true }) (or a new subagent.adminDeleteSession) which is gated by an explicit per-plugin policy (similar to the existing allowModelOverride allowlist in setPluginSubagentOverridePolicies). This keeps the synthetic-fallback safety net intact while giving trusted plugins a documented escape hatch.

  3. Method-scopes side: split the lifecycle of operator-initiated session deletes vs. plugin-initiated, plugin-owned session deletes into two methods, with the plugin variant requiring only operator.write plus ownership proof.

Workaround

For self-hosted users hitting this on every dreaming run, a local patch to the distributed dist/server-plugin-bootstrap-*.js to pass { syntheticScopes: ["operator.admin"] } from deleteSession will silence the error — but this is not a correct upstream change because it removes the security boundary asserted by the test above.

Reproduce

  1. Enable memory-core and set cron.enabled: true.
  2. Trigger a dreaming run (openclaw cron run memory.dreaming.narrative or wait for the schedule).
  3. Observe journalctl --user -u openclaw-gateway: [memory-core/dreaming] failed to delete dreaming subagent session: missing scope: operator.admin

Disclosure: Drafted with assistance from GitHub Copilot CLI based on diagnostics from a self-hosted openclaw deployment.

extent analysis

TL;DR

The most likely fix is to wrap the dreaming cleanup in withPluginRuntimeGatewayRequestScope with an admin-scoped synthetic client on the memory-core side.

Guidance

  • The issue is caused by the memory-core dreaming worker not having the required operator.admin scope to delete sessions.
  • To verify, check the journalctl --user -u openclaw-gateway logs for the error message [memory-core/dreaming] failed to delete dreaming subagent session: missing scope: operator.admin.
  • A possible mitigation is to introduce an opt-in subagent.deleteSession({ asAdmin: true }) method, gated by an explicit per-plugin policy.
  • Another option is to split the lifecycle of operator-initiated session deletes vs. plugin-initiated session deletes into two methods, with the plugin variant requiring only operator.write plus ownership proof.

Example

No code example is provided as the issue requires a design change rather than a simple code fix.

Notes

The provided workaround of passing { syntheticScopes: ["operator.admin"] } from deleteSession is not a correct upstream change as it removes the security boundary asserted by the test.

Recommendation

Apply a workaround by wrapping the dreaming cleanup in withPluginRuntimeGatewayRequestScope with an admin-scoped synthetic client, as this is a reasonable solution given that memory-core is a trusted bundled plugin.

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…

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 memory-core dreaming cleanup fails: subagent deleteSession cannot dispatch sessions.delete (operator.admin required) [1 comments, 2 participants]