Skip to content

fix: catch ClosedResourceError in error handler to prevent crash on client disconnect#2160

Open
giulio-leone wants to merge 2 commits intomodelcontextprotocol:mainfrom
giulio-leone:fix/handle-closed-resource-in-error-handler
Open

fix: catch ClosedResourceError in error handler to prevent crash on client disconnect#2160
giulio-leone wants to merge 2 commits intomodelcontextprotocol:mainfrom
giulio-leone:fix/handle-closed-resource-in-error-handler

Conversation

@giulio-leone
Copy link

Summary

Fixes #2064

When a client disconnects during request processing, _handle_message receives the exception and tries to send a log message back via send_log_message(). Since the write stream is already closed, this raises ClosedResourceError, which is unhandled and crashes the stateless session with an ExceptionGroup.

Root Cause

In lowlevel/server.py, the Exception branch of _handle_message (line ~418) calls session.send_log_message() unconditionally. When the error is a client disconnect, the write stream is already closed, so the chain send_log_message → send_notification → _write_stream.send() raises ClosedResourceError.

This is a different code path from PR #1384, which fixed ClosedResourceError in the message router loop. This fix covers the _handle_post_request → _handle_message → send_log_message error recovery path.

Fix

Wrap the send_log_message() call in a try/except that catches both anyio.ClosedResourceError and anyio.BrokenResourceError, logging a warning instead of crashing. Failing to notify a disconnected client is expected and harmless.

Test Results

475 server tests pass (2 consecutive clean runs).

giulio-leone and others added 2 commits February 28, 2026 04:32
…lient disconnect

When a client disconnects during request processing, _handle_message
receives the exception and tries to send a log message back to the
client via send_log_message(). Since the write stream is already closed,
this raises ClosedResourceError (or BrokenResourceError), which is
unhandled and crashes the stateless session with an ExceptionGroup.

Wrap the send_log_message() call in a try/except that catches both
anyio.ClosedResourceError and anyio.BrokenResourceError, since failing
to notify a disconnected client is expected and harmless.

This is a different code path from PR modelcontextprotocol#1384, which fixed the message
router loop. This fix covers the _handle_post_request → _handle_message
→ send_log_message error recovery path.

Fixes modelcontextprotocol#2064

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

ClientDisconnect during _handle_post_request crashes stateless session with ClosedResourceError

1 participant