fix(memory): handle ENOENT gracefully in readFile instead of throwing

When a memory file doesn't exist yet (e.g. daily log `2026-02-19.md`),
`readFile` now returns `{ text: "", path }` instead of propagating the
ENOENT error. This prevents noisy error responses from the memory read
tool and aligns with the "graceful degradation" recommendation in #9307.

Closes #9307

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniel Zou
2026-02-19 01:35:28 -05:00
committed by Vignesh
parent 8f80e2a467
commit f3f47886ba
2 changed files with 34 additions and 3 deletions

View File

@@ -12,7 +12,7 @@ let searchImpl: () => Promise<unknown[]> = async () => [
source: "memory" as const,
},
];
let readFileImpl: () => Promise<string> = async () => "";
let readFileImpl: () => Promise<unknown> = async () => "";
const stubManager = {
search: vi.fn(async () => await searchImpl()),
@@ -59,7 +59,7 @@ beforeEach(() => {
source: "memory" as const,
},
];
readFileImpl = async () => "";
readFileImpl = async () => ""; // default: return empty string
vi.clearAllMocks();
});
@@ -189,4 +189,23 @@ describe("memory tools", () => {
error: "path required",
});
});
it("returns empty text without error when file does not exist (ENOENT)", async () => {
readFileImpl = async () => {
return { text: "", path: "memory/2026-02-19.md" };
};
const cfg = { agents: { list: [{ id: "main", default: true }] } };
const tool = createMemoryGetTool({ config: cfg });
expect(tool).not.toBeNull();
if (!tool) {
throw new Error("tool missing");
}
const result = await tool.execute("call_enoent", { path: "memory/2026-02-19.md" });
expect(result.details).toEqual({
text: "",
path: "memory/2026-02-19.md",
});
});
});