From 76e7aec0e809b90e395b9db04f6219fdc79b6f93 Mon Sep 17 00:00:00 2001 From: John Brahy Date: Thu, 19 Mar 2026 01:40:52 -0700 Subject: [PATCH] fix(gsd): avoid EISDIR crash in file loader --- src/resources/extensions/gsd/files.ts | 3 ++- .../gsd/tests/files-loadfile-eisdir.test.ts | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts diff --git a/src/resources/extensions/gsd/files.ts b/src/resources/extensions/gsd/files.ts index a444deadc..0c26ab100 100644 --- a/src/resources/extensions/gsd/files.ts +++ b/src/resources/extensions/gsd/files.ts @@ -590,7 +590,8 @@ export async function loadFile(path: string): Promise { try { return await fs.readFile(path, 'utf-8'); } catch (err: unknown) { - if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null; + const code = (err as NodeJS.ErrnoException).code; + if (code === 'ENOENT' || code === 'EISDIR') return null; throw err; } } diff --git a/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts b/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts new file mode 100644 index 000000000..cff1d4876 --- /dev/null +++ b/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts @@ -0,0 +1,20 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import os from "node:os"; +import path from "node:path"; +import fs from "node:fs"; + +import { loadFile } from "../files.ts"; + +test("loadFile returns null for directory paths instead of throwing EISDIR", async () => { + const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-loadfile-eisdir-")); + const dirPath = path.join(tmp, "tasks"); + fs.mkdirSync(dirPath); + + try { + const result = await loadFile(dirPath); + assert.equal(result, null); + } finally { + fs.rmSync(tmp, { recursive: true, force: true }); + } +});