Skip to content

Commit d7c14b5

Browse files
committed
fix(memory-core): silence expected 'missing scope: operator.admin' in dreaming cleanup
The dreaming cron's narrative cleanup calls subagent.deleteSession, which dispatches sessions.delete (ADMIN_SCOPE). From a background cron there is no inherited operator scope, so the plugin subagent falls through to a synthetic operator client that intentionally defaults to [WRITE_SCOPE] and does not mint admin (codified by 'rejects fallback session deletion without minting admin scope' in src/gateway/server-plugins.test.ts). Result: every dreaming cycle logged memory-core: narrative session cleanup failed for <phase> phase: missing scope: operator.admin The cleanup was already best-effort (try/catch), but the warn surfaced to users on every cycle and made healthy instances look broken. Treat the 'missing scope: operator.admin' case as an expected no-op and suppress the warn for just that specific error. Any other cleanup error (network, timeout, etc.) still surfaces as warn. Adds a test locking in the new behavior; existing test covering non-scope cleanup failures continues to pass unchanged.
1 parent 89706d3 commit d7c14b5

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

extensions/memory-core/src/dreaming-narrative.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,31 @@ describe("generateAndAppendDreamNarrative", () => {
678678
);
679679
});
680680

681+
it("does not warn when cleanup fails with missing operator.admin scope (background cron fallback path)", async () => {
682+
// The plugin subagent running from a background cron falls through to a
683+
// synthetic operator client without admin scope (see
684+
// `rejects fallback session deletion without minting admin scope` in
685+
// src/gateway/server-plugins.test.ts). `sessions.delete` requires
686+
// operator.admin, so this error fires on every dreaming cycle and is
687+
// expected — it should not surface as a user-visible warning.
688+
const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");
689+
const subagent = createMockSubagent("");
690+
subagent.deleteSession.mockRejectedValue(new Error("missing scope: operator.admin"));
691+
const logger = createMockLogger();
692+
693+
await generateAndAppendDreamNarrative({
694+
subagent,
695+
workspaceDir,
696+
data: { phase: "rem", snippets: ["some memory"] },
697+
logger,
698+
});
699+
700+
expect(subagent.deleteSession).toHaveBeenCalledOnce();
701+
expect(logger.warn).not.toHaveBeenCalledWith(
702+
expect.stringContaining("narrative session cleanup failed"),
703+
);
704+
});
705+
681706
it("handles subagent error gracefully", async () => {
682707
const workspaceDir = await createTempWorkspace("openclaw-dreaming-narrative-");
683708
const subagent = createMockSubagent("");

extensions/memory-core/src/dreaming-narrative.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,9 +932,21 @@ export async function generateAndAppendDreamNarrative(params: {
932932
try {
933933
await params.subagent.deleteSession({ sessionKey });
934934
} catch (cleanupErr) {
935-
params.logger.warn(
936-
`memory-core: narrative session cleanup failed for ${params.data.phase} phase: ${formatErrorMessage(cleanupErr)}`,
937-
);
935+
const errMessage = formatErrorMessage(cleanupErr);
936+
// `sessions.delete` requires operator.admin. When dreaming runs from a
937+
// background cron (no inherited operator scope) the plugin subagent
938+
// falls through to a synthetic operator client that intentionally
939+
// defaults to [operator.write] and does not mint admin — see
940+
// `rejects fallback session deletion without minting admin scope` in
941+
// src/gateway/server-plugins.test.ts. That path is guaranteed to reject
942+
// delete with "missing scope: operator.admin" on every cycle, so treat
943+
// it as an expected no-op rather than emitting noise. Genuine failures
944+
// (any other error) are still surfaced as warn.
945+
if (!errMessage.includes("missing scope: operator.admin")) {
946+
params.logger.warn(
947+
`memory-core: narrative session cleanup failed for ${params.data.phase} phase: ${errMessage}`,
948+
);
949+
}
938950
}
939951

940952
await scrubDreamingNarrativeArtifacts(params.logger).catch((scrubErr: unknown) => {

0 commit comments

Comments
 (0)