Skip to content

memory-core dreaming plugin: deleteSession() fails 100% → sessions.json leak → gateway OOM #69187

Description

@r0gerliu

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

  1. Session-store bloat: 1368 entries × ~60KB metadata = sessions.json grows linearly without bound.
  2. Transcript leak: Each leaked entry has a corresponding .jsonl transcript file (5-8KB each). We found 1423 orphan transcripts.
  3. 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).
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions