fix: handle ClientDisconnect gracefully instead of returning HTTP 500 #1947
+269
−49
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
StreamableHTTPServerTransport._handle_post_request(and related SSE handlers) incorrectly handlesstarlette.requests.ClientDisconnectexceptions. When a client disconnects during a request, the broadexcept Exceptionhandler catches it and:logger.exception()This happens during normal operations: network timeouts, user cancels request, load balancer timeouts, mobile client network interruptions. These are client-side events, not server failures.
Solution
Catch
ClientDisconnectexplicitly before the genericexcept Exceptionhandlers:handle_request()— wraps all HTTP method dispatching (POST, GET, DELETE) with a singleexcept ClientDisconnectthat logs at DEBUG level. This is the primary fix that prevents the 500 response for the most common case (client disconnects during body reading or response sending)._handle_get_request()SSE handlers — catchesClientDisconnectin the standalone SSE writer and SSE response to cleanly close streams without ERROR logging.Event replay handlers — catches
ClientDisconnectin the replay sender, replay response, and outer replay handler.All handlers log at
DEBUGlevel since client disconnection is expected behavior, not an error condition.Testing
Added regression tests in
tests/issues/test_1648_client_disconnect_500.py:test_client_disconnect_does_not_produce_500— verifies no ERROR-level logs are produced when a client disconnects during a requesttest_server_healthy_after_client_disconnect— verifies the server remains operational and can accept new requests after a client disconnectsCloses #1648