Dreaming plugin: deleteSession() fails on every cron invocation, leaking session entries
Summary
The memory-core dreaming narrative plugin (dreaming-narrative-BFx7ugb_.js) runs a 3-phase cron job (light/REM/deep) that 100% leaks its subagent session entries because deleteSession() in the finally block fails with one of two errors on every single invocation.
Over 4 days on a workspace with dreaming enabled, we accumulated 1368 orphaned dreaming-narrative-* entries in sessions.json, bloating it to 187MB. Combined with orphan .tmp files from atomic writes (see separate issue), this caused the gateway to consume 4GB+ RSS on startup → OOM → crash-restart loop.
Environment
- OpenClaw: latest (installed via brew/npm,
/opt/homebrew/lib/node_modules/openclaw/)
- OS: macOS 15.4 (Apple Silicon)
- Node: v22.22.1
- Workspace has
plugins.entries.memory-core.config.dreaming.enabled = true
Reproduction
Any workspace with dreaming enabled. Cron schedule is 0 3 * * * Asia/Taipei.
After 1 day, you'll see 3 leaked dreaming-narrative-{light,rem,deep}-{hash}-{nowMs} entries per workspace in ~/.openclaw/agents/main/sessions/sessions.json.
Evidence from gateway.err.log
The cleanup code at dreaming-narrative-BFx7ugb_.js around line 592 is:
} finally {
// ... wait for run settle ...
try {
await params.subagent.deleteSession({ sessionKey });
} catch (cleanupErr) {
params.logger.warn(`memory-core: narrative session cleanup failed for ${params.data.phase} phase: ${formatErrorMessage(cleanupErr)}`);
}
await scrubDreamingNarrativeArtifacts(params.logger).catch(...)
}
The deleteSession call fails with two alternating errors across invocations:
Error A — Runtime lifecycle mismatch:
[plugins] memory-core: narrative session cleanup failed for rem phase:
Plugin runtime subagent methods are only available during a gateway request.
Occurs when cleanup runs after the gateway request that triggered the cron has ended. The params.subagent handle is bound to a request lifecycle that no longer exists by the time finally executes.
Error B — Missing scope:
[plugins] memory-core: narrative session cleanup failed for light phase:
missing scope: operator.admin
Occurs on other paths — plugin lacks the operator.admin scope required by deleteSession.
Both appear in gateway.err.log on every single dreaming cron firing. We have hundreds of these warnings over days. Count of narrative session cleanup failed: every light/REM/deep cycle (3/day per workspace), 100% failure rate.
Impact
- Session-store bloat: 1368 entries × ~60KB metadata = sessions.json grows linearly without bound.
- Transcript leak: Each leaked entry has a corresponding
.jsonl transcript file (5-8KB each). We found 1423 orphan transcripts.
- Startup OOM: Gateway eagerly loads entire
sessions.json at startup. At 187MB this pushed RSS to 4GB+ and triggered repeated OOM kills / launchd restarts (crash loop).
- Secondary failure: Every failed gateway write leaves a
sessions.json.<uuid>.tmp artifact (atomic rename pattern); in 4 days we accumulated 172 orphan .tmp files totaling 5.66GB.
Suggested Fixes
Option 1 — Use a lifecycle-independent delete API. The plugin probably needs a direct handle to the session store (not the request-scoped params.subagent) so that deleteSession works in the cron finally block after the triggering request has ended.
Option 2 — Grant operator.admin scope to memory-core plugin manifest. At minimum this fixes Error B.
Option 3 — Orphan-sweep on plugin init. At plugin startup, enumerate all session keys matching dreaming-narrative-* that are older than some TTL (e.g. 24h) and delete them unconditionally. Self-heals any past leaks.
Option 4 — Don't persist dreaming sessions to sessions.json at all. These sessions are short-lived scratch workspaces for a specific task. Consider a dedicated ephemeral-session path that bypasses the main session store.
Our Local Workaround (FYI)
While waiting for a fix we deployed:
- A LaunchAgent (
ai.openclaw.dreaming-cleanup) running 4x/day to archive dreaming-narrative-* entries > 24h old and delete orphan sessions.json.*.tmp files > 1h old
session.maintenance in openclaw.json set to enforce mode with a 1GB disk budget so future growth triggers eviction at gateway startup
These mitigate the symptom but the underlying deleteSession failure should be fixed upstream so fresh workspaces don't hit the crash-loop.
Related Log Excerpts
2026-04-19T03:08:11.595+08:00 [plugins] memory-core: narrative session cleanup failed for rem phase: Plugin runtime subagent methods are only available during a gateway request.
2026-04-19T03:08:13.068+08:00 [plugins] memory-core: narrative session cleanup failed for deep phase: Plugin runtime subagent methods are only available during a gateway request.
2026-04-19T03:08:14.397+08:00 [plugins] memory-core: narrative session cleanup failed for light phase: Plugin runtime subagent methods are only available during a gateway request.
2026-04-20T03:02:40.294+08:00 [plugins] memory-core: narrative session cleanup failed for light phase: missing scope: operator.admin
2026-04-20T03:04:41.382+08:00 [plugins] memory-core: narrative session cleanup failed for rem phase: missing scope: operator.admin
2026-04-20T03:06:29.792+08:00 [plugins] memory-core: narrative session cleanup failed for deep phase: missing scope: operator.admin
Happy to provide more diagnostic data from the affected workspace if useful.
Dreaming plugin:
deleteSession()fails on every cron invocation, leaking session entriesSummary
The
memory-coredreaming narrative plugin (dreaming-narrative-BFx7ugb_.js) runs a 3-phase cron job (light/REM/deep) that 100% leaks its subagent session entries becausedeleteSession()in thefinallyblock fails with one of two errors on every single invocation.Over 4 days on a workspace with dreaming enabled, we accumulated 1368 orphaned
dreaming-narrative-*entries insessions.json, bloating it to 187MB. Combined with orphan.tmpfiles from atomic writes (see separate issue), this caused the gateway to consume 4GB+ RSS on startup → OOM → crash-restart loop.Environment
/opt/homebrew/lib/node_modules/openclaw/)plugins.entries.memory-core.config.dreaming.enabled = trueReproduction
Any workspace with dreaming enabled. Cron schedule is
0 3 * * *Asia/Taipei.After 1 day, you'll see 3 leaked
dreaming-narrative-{light,rem,deep}-{hash}-{nowMs}entries per workspace in~/.openclaw/agents/main/sessions/sessions.json.Evidence from gateway.err.log
The cleanup code at
dreaming-narrative-BFx7ugb_.jsaround line 592 is:The
deleteSessioncall fails with two alternating errors across invocations:Error A — Runtime lifecycle mismatch:
Occurs when cleanup runs after the gateway request that triggered the cron has ended. The
params.subagenthandle is bound to a request lifecycle that no longer exists by the timefinallyexecutes.Error B — Missing scope:
Occurs on other paths — plugin lacks the
operator.adminscope required bydeleteSession.Both appear in
gateway.err.logon every single dreaming cron firing. We have hundreds of these warnings over days. Count ofnarrative session cleanup failed: every light/REM/deep cycle (3/day per workspace), 100% failure rate.Impact
.jsonltranscript file (5-8KB each). We found 1423 orphan transcripts.sessions.jsonat startup. At 187MB this pushed RSS to 4GB+ and triggered repeated OOM kills / launchd restarts (crash loop).sessions.json.<uuid>.tmpartifact (atomic rename pattern); in 4 days we accumulated 172 orphan .tmp files totaling 5.66GB.Suggested Fixes
Option 1 — Use a lifecycle-independent delete API. The plugin probably needs a direct handle to the session store (not the request-scoped
params.subagent) so thatdeleteSessionworks in the cronfinallyblock after the triggering request has ended.Option 2 — Grant
operator.adminscope tomemory-coreplugin manifest. At minimum this fixes Error B.Option 3 — Orphan-sweep on plugin init. At plugin startup, enumerate all session keys matching
dreaming-narrative-*that are older than some TTL (e.g. 24h) and delete them unconditionally. Self-heals any past leaks.Option 4 — Don't persist dreaming sessions to
sessions.jsonat all. These sessions are short-lived scratch workspaces for a specific task. Consider a dedicated ephemeral-session path that bypasses the main session store.Our Local Workaround (FYI)
While waiting for a fix we deployed:
ai.openclaw.dreaming-cleanup) running 4x/day to archivedreaming-narrative-*entries > 24h old and delete orphansessions.json.*.tmpfiles > 1h oldsession.maintenanceinopenclaw.jsonset toenforcemode with a 1GB disk budget so future growth triggers eviction at gateway startupThese mitigate the symptom but the underlying
deleteSessionfailure should be fixed upstream so fresh workspaces don't hit the crash-loop.Related Log Excerpts
Happy to provide more diagnostic data from the affected workspace if useful.