From bd32c871b7c3357ebc48ece0bfbdc60b3180538b Mon Sep 17 00:00:00 2001 From: Dotta Date: Thu, 5 Mar 2026 15:23:25 -0600 Subject: [PATCH] fix(run-log-store): close fd leak in log append that caused spawn EBADF The append method created a new WriteStream for every log chunk and resolved the promise on the end callback (data flushed) rather than the close event (fd released). Over many agent runs the leaked fds corrupted the fd table, causing child_process.spawn to fail with EBADF. Replace with fs.appendFile which properly opens, writes, and closes the fd before resolving. Co-Authored-By: Claude Opus 4.6 --- server/src/services/run-log-store.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/server/src/services/run-log-store.ts b/server/src/services/run-log-store.ts index 4ce60366..bbc98391 100644 --- a/server/src/services/run-log-store.ts +++ b/server/src/services/run-log-store.ts @@ -1,4 +1,4 @@ -import { createReadStream, createWriteStream, promises as fs } from "node:fs"; +import { createReadStream, promises as fs } from "node:fs"; import path from "node:path"; import { createHash } from "node:crypto"; import { notFound } from "../errors.js"; @@ -113,11 +113,7 @@ function createLocalFileRunLogStore(basePath: string): RunLogStore { stream: event.stream, chunk: event.chunk, }); - await new Promise((resolve, reject) => { - const stream = createWriteStream(absPath, { flags: "a", encoding: "utf8" }); - stream.on("error", reject); - stream.end(`${line}\n`, () => resolve()); - }); + await fs.appendFile(absPath, `${line}\n`, "utf8"); }, async finalize(handle) {