From 1b84316a91dc32ce57fcd3f8b457f6de80f73dd3 Mon Sep 17 00:00:00 2001 From: cxbAsDev Date: Sat, 4 Jul 2026 13:42:12 +0800 Subject: [PATCH] fix(mcp): suppress unhandled error on stderr pipe in stdio transport (#99803) * fix(mcp): suppress unhandled error on stderr pipe in stdio transport When child.stderr is piped to stderrStream without an error handler, a stream-level error (EPIPE, I/O failure) crashes the process. Add a noop error handler before the pipe, consistent with the error handlers already present on stdin and stdout. Co-Authored-By: Claude * test(mcp): add regression test for stderr pipe error suppression Co-Authored-By: Claude * fix(mcp): report stderr stream errors * fix(mcp): report stderr stream errors --------- Co-authored-by: Claude Co-authored-by: Vincent Koc --- src/agents/mcp-stdio-transport.test.ts | 19 +++++++++++++++++++ src/agents/mcp-stdio-transport.ts | 1 + 2 files changed, 20 insertions(+) diff --git a/src/agents/mcp-stdio-transport.test.ts b/src/agents/mcp-stdio-transport.test.ts index f487fb2059c6..1764983b30ff 100644 --- a/src/agents/mcp-stdio-transport.test.ts +++ b/src/agents/mcp-stdio-transport.test.ts @@ -204,4 +204,23 @@ describe("OpenClawStdioClientTransport", () => { "write after end", ); }); + + it("reports stderr pipe errors without an unhandled error crash", async () => { + const child = new MockChildProcess(); + spawnMock.mockReturnValue(child); + + const transport = new OpenClawStdioClientTransport({ command: "npx", stderr: "pipe" }); + const onerror = vi.fn(); + Object.assign(transport, { onerror }); + const started = transport.start(); + child.emit("spawn"); + await started; + + const error = new Error("simulated pipe error"); + expect(() => child.stderr?.emit("error", error)).not.toThrow(); + expect(onerror).toHaveBeenCalledWith(error); + + child.stderr.write("server diagnostic"); + expect(transport.stderr?.read()?.toString()).toBe("server diagnostic"); + }); }); diff --git a/src/agents/mcp-stdio-transport.ts b/src/agents/mcp-stdio-transport.ts index 99ab66235f32..2e268128b803 100644 --- a/src/agents/mcp-stdio-transport.ts +++ b/src/agents/mcp-stdio-transport.ts @@ -86,6 +86,7 @@ export class OpenClawStdioClientTransport implements Transport { }); child.stdout?.on("error", (error: Error) => this.onerror?.(error)); if (this.stderrStream && child.stderr) { + child.stderr.on("error", (error: Error) => this.onerror?.(error)); child.stderr.pipe(this.stderrStream); } });