fix(streamable_http): send response on ClientDisconnect to satisfy middleware chains#5
Merged
wiggzz merged 2 commits intodbt-labs/patched-1.27.0from May 5, 2026
Conversation
…ddleware chains
When ClientDisconnect is caught in _handle_post_request, send a 202 Accepted
response so that Starlette BaseHTTPMiddleware wrappers don't raise
RuntimeError('No response returned'). The ASGI server will drop the response
if the socket is already closed.
Fixes ai-codegen-api 'No response returned' error when client disconnects
mid-POST. The existing ClientDisconnectHandlerMiddleware can no longer
intercept the early return since BaseHTTPMiddleware wraps above it.
…for ClientDisconnect 499 is the nginx convention for 'Client Closed Request' — more semantically correct than 202 Accepted for a cancelled request.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
When
ClientDisconnectis caught in_handle_post_request, returning early without sending a response works fine for bare ASGI apps, but ai-codegen-api wraps the MCP transport in StarletteBaseHTTPMiddlewarewhich raisesRuntimeError('No response returned')when the ASGI app doesn't callsend.The existing
ClientDisconnectHandlerMiddlewarecan't catch this becauseBaseHTTPMiddlewarelayers wrap above it in the middleware chain.Solution
Send a 499 (Client Closed Request) response when ClientDisconnect is caught. The ASGI server (uvicorn) will simply drop the response if the socket is already closed, but the middleware chain sees a response was sent and doesn't error.
Uses 499 (nginx convention for "Client Closed Request") rather than 202 — more semantically correct for a cancelled request. Builds the
Responsedirectly to avoid theHTTPStatustype hint limitation (499 is not in Python's stdlib HTTPStatus enum).Tests
Updated 2 existing tests in
tests/server/streamable_http/test_client_disconnect_post.py:test_client_disconnect_sends_response(renamed fromdoes_not_send_response) — verifies 499 response is senttest_client_disconnect_writer_suppresses_errors— verifies response is still sent even when writer is brokenUpstream context
Inspired by upstream PR modelcontextprotocol/python-sdk#1647 which also uses 499 for this case. Tracking issue: modelcontextprotocol/python-sdk#1648.