From 22d4881d8ae8578198150f484ac0f143b99569c1 Mon Sep 17 00:00:00 2001 From: corvid-agent <0xOpenBytes@gmail.com> Date: Thu, 12 Feb 2026 22:22:42 -0700 Subject: [PATCH] fix: call onerror for silently swallowed transport errors Nested try/catch blocks in WebStandardStreamableHTTPServerTransport's handlePostRequest were returning error responses without invoking the onerror callback, making transport errors invisible to consumers. Fixes: - JSON parsing errors (req.json() failures) now call onerror - JSON-RPC message validation errors now call onerror - writeSSEEvent failures now call onerror instead of silently returning false Closes #1395 Co-Authored-By: Claude Opus 4.6 --- .changeset/fix-transport-onerror-swallowed.md | 5 +++++ packages/server/src/server/streamableHttp.ts | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 .changeset/fix-transport-onerror-swallowed.md diff --git a/.changeset/fix-transport-onerror-swallowed.md b/.changeset/fix-transport-onerror-swallowed.md new file mode 100644 index 000000000..4702f2666 --- /dev/null +++ b/.changeset/fix-transport-onerror-swallowed.md @@ -0,0 +1,5 @@ +--- +'@modelcontextprotocol/server': patch +--- + +Call `onerror` callback for transport errors that were previously silently swallowed. Nested try/catch blocks in `handlePostRequest` for JSON parsing and JSON-RPC validation now invoke `onerror` before returning error responses. The `writeSSEEvent` method also reports errors via `onerror` instead of silently returning `false`. diff --git a/packages/server/src/server/streamableHttp.ts b/packages/server/src/server/streamableHttp.ts index b5038d018..28d79fa28 100644 --- a/packages/server/src/server/streamableHttp.ts +++ b/packages/server/src/server/streamableHttp.ts @@ -569,7 +569,8 @@ export class WebStandardStreamableHTTPServerTransport implements Transport { eventData += `data: ${JSON.stringify(message)}\n\n`; controller.enqueue(encoder.encode(eventData)); return true; - } catch { + } catch (error) { + this.onerror?.(error as Error); return false; } } @@ -627,7 +628,8 @@ export class WebStandardStreamableHTTPServerTransport implements Transport { if (options?.parsedBody === undefined) { try { rawMessage = await req.json(); - } catch { + } catch (error) { + this.onerror?.(error as Error); return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON'); } } else { @@ -641,7 +643,8 @@ export class WebStandardStreamableHTTPServerTransport implements Transport { messages = Array.isArray(rawMessage) ? rawMessage.map(msg => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(rawMessage)]; - } catch { + } catch (error) { + this.onerror?.(error as Error); return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON-RPC message'); }