Title: fix: handle ClosedResourceError in _handle_message error recovery path by BabyChrist666 · Pull Request #2072 · modelcontextprotocol/python-sdk · GitHub
Open Graph Title: fix: handle ClosedResourceError in _handle_message error recovery path by BabyChrist666 · Pull Request #2072 · modelcontextprotocol/python-sdk
X Title: fix: handle ClosedResourceError in _handle_message error recovery path by BabyChrist666 · Pull Request #2072 · modelcontextprotocol/python-sdk
Description: Summary Closes #2064 When a client disconnects while a stateless streamable-HTTP server is processing a request, the error handler in _handle_message tries to send_log_message() back to the client. Since the session was already terminated and the write stream closed, this raises ClosedResourceError, which is unhandled and crashes the stateless session with an ExceptionGroup. This is a different code path from what PR #1384 fixed. That PR addressed ClosedResourceError in the message router loop. This bug is in the error recovery path: catch exception → try to log it to client → write stream already closed → crash. Fix Wrap the send_log_message() call in _handle_message's exception handler with a try/except that catches anyio.ClosedResourceError and anyio.BrokenResourceError. Failing to notify a disconnected client is expected and harmless — we just log it at debug level and move on. # Before: crashes if client disconnected await session.send_log_message(level="error", ...) # After: gracefully handles disconnected client try: await session.send_log_message(level="error", ...) except (anyio.ClosedResourceError, anyio.BrokenResourceError): logger.debug("Could not send error log: client disconnected") This follows the same pattern already used elsewhere in the codebase (session.py:406, streamable_http.py:587, streamable_http.py:1009, etc.). Test plan Added 4 new tests in test_lowlevel_exception_handling.py: test_exception_handling_with_disconnected_client[ClosedResourceError] test_exception_handling_with_disconnected_client[BrokenResourceError] test_exception_handling_with_disconnected_client_raise_exceptions[ClosedResourceError] test_exception_handling_with_disconnected_client_raise_exceptions[BrokenResourceError] All 10 existing + new tests pass ruff lint + format clean pyright clean (0 errors) 🤖 Generated with Claude Code
Open Graph Description: Summary Closes #2064 When a client disconnects while a stateless streamable-HTTP server is processing a request, the error handler in _handle_message tries to send_log_message() back to the client....
X Description: Summary Closes #2064 When a client disconnects while a stateless streamable-HTTP server is processing a request, the error handler in _handle_message tries to send_log_message() back to the client....
Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/pull/2072
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:b7f49c89-95cb-73a3-b310-d03a91be3ef1 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | CAD2:186FB1:10887CA:163C1C9:6A5BB156 |
| html-safe-nonce | 6c4fa679963cb76ecd6d995b881b54280ca567ecdae89e4f40a040617567c5ac |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDQUQyOjE4NkZCMToxMDg4N0NBOjE2M0MxQzk6NkE1QkIxNTYiLCJ2aXNpdG9yX2lkIjoiNTM4ODMyNDU1NTI1MjgwNTk3NCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | d7827704d371dfa981d0079abc82aeeffe0cae53850a947968e4b4c1000353a4 |
| hovercard-subject-tag | pull_request:3292582584 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/modelcontextprotocol/python-sdk/pull/2072/files |
| twitter:image | https://avatars.githubusercontent.com/u/251679698?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/251679698?s=400&v=4 |
| og:image:alt | Summary Closes #2064 When a client disconnects while a stateless streamable-HTTP server is processing a request, the error handler in _handle_message tries to send_log_message() back to the client.... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5290d7e14309ad1e76106a9c4237bd1041517e83ea182c8ab756752cb0c6940b |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git |
| octolytics-dimension-user_id | 182288589 |
| octolytics-dimension-user_login | modelcontextprotocol |
| octolytics-dimension-repository_id | 862584018 |
| octolytics-dimension-repository_nwo | modelcontextprotocol/python-sdk |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 862584018 |
| octolytics-dimension-repository_network_root_nwo | modelcontextprotocol/python-sdk |
| turbo-body-classes | logged-out env-production page-responsive full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 9c975978430e9ad293956f2bbdaf153b1bd84a99 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width