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); } });