From da170118396400f5455206c8ff2acecfe4eda9df Mon Sep 17 00:00:00 2001 From: VACInc <3279061+VACInc@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:08:25 -0400 Subject: [PATCH] fix(gateway): guard transcript cleanup emits on rm failure --- src/gateway/session-utils.fs.test.ts | 20 ++++++++++++++++++++ src/gateway/session-utils.fs.ts | 8 +++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/gateway/session-utils.fs.test.ts b/src/gateway/session-utils.fs.test.ts index d26532dece0..fa77b9fa4d1 100644 --- a/src/gateway/session-utils.fs.test.ts +++ b/src/gateway/session-utils.fs.test.ts @@ -242,6 +242,26 @@ describe("cleanupArchivedSessionTranscripts", () => { expect(fs.existsSync(deletedPath)).toBe(false); expect(emitSpy).not.toHaveBeenCalled(); }); + + test("does not count or emit when reset archive removal fails", async () => { + const emitSpy = vi.spyOn(transcriptEvents, "emitSessionTranscriptUpdate"); + const now = Date.now(); + const resetName = `cleanup-reset-fail.jsonl.reset.${formatSessionArchiveTimestamp(now - 10_000)}`; + const resetPath = path.join(tmpDir, resetName); + fs.writeFileSync(resetPath, '{"type":"session"}\n', "utf-8"); + vi.spyOn(fs.promises, "rm").mockRejectedValueOnce(new Error("rm failed")); + + const result = await cleanupArchivedSessionTranscripts({ + directories: [tmpDir], + olderThanMs: 1_000, + reason: "reset", + nowMs: now, + }); + + expect(result.removed).toBe(0); + expect(fs.existsSync(resetPath)).toBe(true); + expect(emitSpy).not.toHaveBeenCalled(); + }); }); describe("readLastMessagePreviewFromTranscript", () => { diff --git a/src/gateway/session-utils.fs.ts b/src/gateway/session-utils.fs.ts index e38f82ffa13..b8341e420d5 100644 --- a/src/gateway/session-utils.fs.ts +++ b/src/gateway/session-utils.fs.ts @@ -266,7 +266,13 @@ export async function cleanupArchivedSessionTranscripts(opts: { if (!stat?.isFile()) { continue; } - await fs.promises.rm(fullPath).catch(() => undefined); + const removedFromDisk = await fs.promises.rm(fullPath).then( + () => true, + () => false, + ); + if (!removedFromDisk) { + continue; + } removed += 1; if (reason === "reset") { emitSessionTranscriptUpdate(fullPath);