Skip to content

Commit 1b84316

Browse files
cxbAsDevclaudevincentkoc
authored
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 <[email protected]> * test(mcp): add regression test for stderr pipe error suppression Co-Authored-By: Claude <[email protected]> * fix(mcp): report stderr stream errors * fix(mcp): report stderr stream errors --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
1 parent acdaf8a commit 1b84316

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

src/agents/mcp-stdio-transport.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,23 @@ describe("OpenClawStdioClientTransport", () => {
204204
"write after end",
205205
);
206206
});
207+
208+
it("reports stderr pipe errors without an unhandled error crash", async () => {
209+
const child = new MockChildProcess();
210+
spawnMock.mockReturnValue(child);
211+
212+
const transport = new OpenClawStdioClientTransport({ command: "npx", stderr: "pipe" });
213+
const onerror = vi.fn();
214+
Object.assign(transport, { onerror });
215+
const started = transport.start();
216+
child.emit("spawn");
217+
await started;
218+
219+
const error = new Error("simulated pipe error");
220+
expect(() => child.stderr?.emit("error", error)).not.toThrow();
221+
expect(onerror).toHaveBeenCalledWith(error);
222+
223+
child.stderr.write("server diagnostic");
224+
expect(transport.stderr?.read()?.toString()).toBe("server diagnostic");
225+
});
207226
});

src/agents/mcp-stdio-transport.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export class OpenClawStdioClientTransport implements Transport {
8686
});
8787
child.stdout?.on("error", (error: Error) => this.onerror?.(error));
8888
if (this.stderrStream && child.stderr) {
89+
child.stderr.on("error", (error: Error) => this.onerror?.(error));
8990
child.stderr.pipe(this.stderrStream);
9091
}
9192
});

0 commit comments

Comments
 (0)