Skip to content

Handle Errno::ECONNRESET in SSE stream operations#249

Open
koic wants to merge 1 commit intomodelcontextprotocol:mainfrom
koic:fix_econnreset_in_sse_notification
Open

Handle Errno::ECONNRESET in SSE stream operations#249
koic wants to merge 1 commit intomodelcontextprotocol:mainfrom
koic:fix_econnreset_in_sse_notification

Conversation

@koic
Copy link
Member

@koic koic commented Mar 1, 2026

Motivation and Context

Errno::ECONNRESET is a SystemCallError, not an IOError, so it was not caught by the existing rescue IOError, Errno::EPIPE clauses. When a client disconnected with a TCP RST during SSE notification broadcast, the unhandled exception aborted the entire broadcast loop, causing notifications to be lost for all remaining sessions.

This caused the tools-call-with-logging conformance scenario to fail in CI (#248), where stale sessions from prior scenarios triggered ECONNRESET on the first notification write, aborting the broadcast and losing log notifications.

Add Errno::ECONNRESET to all four rescue clauses in StreamableHTTPTransport: send_notification (targeted and broadcast), send_response_to_stream, and send_keepalive_ping.

How Has This Been Tested?

Added a repro test to verify the fix and prevent regression.

Breaking Changes

None.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

@koic koic marked this pull request as ready for review March 1, 2026 04:07
atesgoral
atesgoral previously approved these changes Mar 1, 2026
Copy link
Contributor

@atesgoral atesgoral left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the comprehensive tests!

`Errno::ECONNRESET` is a `SystemCallError`, not an `IOError`, so it was
not caught by the existing `rescue IOError, Errno::EPIPE` clauses. When
a client disconnected with a TCP RST during SSE notification broadcast,
the unhandled exception aborted the entire broadcast loop, causing
notifications to be lost for all remaining sessions.

This caused the `tools-call-with-logging` conformance scenario to fail
in CI (modelcontextprotocol#248), where stale sessions from prior scenarios triggered
`ECONNRESET` on the first notification write, aborting the broadcast
and losing log notifications.

Add `Errno::ECONNRESET` to all four rescue clauses in
`StreamableHTTPTransport`: `send_notification` (targeted and broadcast),
`send_response_to_stream`, and `send_keepalive_ping`.
@koic koic force-pushed the fix_econnreset_in_sse_notification branch from a1ad406 to 9c1c249 Compare March 1, 2026 08:28
@koic
Copy link
Member Author

koic commented Mar 1, 2026

There were conflicts in the source code, so it has been rebased onto the latest main branch. Could you review it again?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants