Skip to content

fix: close upstream LLM stream on client disconnect (port #30245) - #184

Merged
prakhar-prakash-juspay merged 1 commit into
release/v1.83.3from
fix/close-upstream-on-disconnect-30245
Jun 15, 2026
Merged

fix: close upstream LLM stream on client disconnect (port #30245)#184
prakhar-prakash-juspay merged 1 commit into
release/v1.83.3from
fix/close-upstream-on-disconnect-30245

Conversation

@prakhar-prakash-juspay

Copy link
Copy Markdown
Collaborator

On client disconnect mid-stream, Starlette abandons the response body iterator without calling aclose(), leaving the upstream vLLM connection open and the GPU slot held until GC (zombie streams -> pool/slot starvation -> 540s timeouts under load).

Wrap the streaming response so its call finally force-closes both the body iterator and the upstream generator, triggering the existing response.aclose() cleanup; add BaseModelResponseIterator.aclose()/http_response so the close reaches the live connection. Both proxy streaming paths (/chat/completions and /v1/messages) are covered via create_response.

Ports BerriAI#30245. Verified: 92 tests pass; ruff clean; black-clean on added lines.

Relevant issues

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Type

🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test

Changes

On client disconnect mid-stream, Starlette abandons the response body iterator without calling aclose(), leaving the upstream vLLM connection open and the GPU slot held until GC (zombie streams -> pool/slot starvation -> 540s timeouts under load).

Wrap the streaming response so its __call__ finally force-closes both the body iterator and the upstream generator, triggering the existing response.aclose() cleanup; add BaseModelResponseIterator.aclose()/http_response so the close reaches the live connection. Both proxy streaming paths (/chat/completions and /v1/messages) are covered via create_response.

Ports BerriAI#30245. Verified: 92 tests pass; ruff clean; black-clean on added lines.

Co-authored-by: Claude <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@prakhar-prakash-juspay
prakhar-prakash-juspay merged commit 14635de into release/v1.83.3 Jun 15, 2026
3 of 4 checks passed
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.

3 participants