Jump to solution
Verify

The Fix

pip install urllib3==2.3.0

Based on closed urllib3/urllib3 issue #2868 · PR/commit linked

Jump to Verify Open PR/Commit
@@ -0,0 +1 @@ @@ -0,0 +1 @@ +Added ``HTTPResponse.shutdown()`` to stop any ongoing or future reads for a specific response. It calls ``shutdown(SHUT_RD)`` on the underlying socket. diff --git a/src/urllib3/connection.py b/src/urllib3/connection.py index 4195ee0306..591ac407bc 100644
repro.py
main [MainThread] starting server server [Thread-1] listening on port 10000 main [MainThread] starting client client [Thread-2] opening connection main [MainThread] sleeping a while server [Thread-1] starting stream 127.0.0.1 - - [05/Jan/2023 13:38:11] "GET / HTTP/1.1" 200 - server [Thread-1] wrote 10 bytes client [Thread-2] reading data client [Thread-2] read 10 bytes main [MainThread] about to close response main [MainThread] closed response client [Thread-2] failed: <some kind of I/O error> client [Thread-2] no longer reading main [MainThread] about to clear connection pool main [MainThread] cleared connection pool main [MainThread] exiting
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Upgrade to fixed release\npip install urllib3==2.3.0\nWhen NOT to use: This fix should not be used if the application requires blocking reads to complete before closing.\n\n

Why This Fix Works in Production

  • Trigger: trying to close a response hangs if a blocking read is happening on another thread
  • Mechanism: Added HTTPResponse.shutdown() to stop blocking reads, allowing the client to handle socket errors appropriately.
  • Why the fix works: Added HTTPResponse.shutdown() to stop blocking reads, allowing the client to handle socket errors appropriately. (first fixed release: 2.3.0).
Production impact:
  • If left unfixed, failures can be intermittent under concurrency (hard to reproduce; shows up as sporadic 5xx/timeouts).

Why This Breaks in Prod

  • Shows up under Python 3.7.13 in real deployments (not just unit tests).
  • Production symptom (often without a traceback): trying to close a response hangs if a blocking read is happening on another thread

Proof / Evidence

  • GitHub issue: #2868
  • Fix PR: https://github.com/urllib3/urllib3/pull/3527
  • First fixed release: 2.3.0
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-09
  • Confidence: 0.95
  • Did this fix it?: Yes (upstream fix exists)
  • Own content ratio: 0.50

Discussion

High-signal excerpts from the issue thread (symptoms, repros, edge-cases).

“Here's something I just came up with that appears to work, but it's pretty hacky and I'm not sure how portable it is: When I…”
@eli-darkly · 2023-01-05 · confirmation · source
“Using the socket module to have a thread reading from a socket and another one closing it, while the server is sending chunks of data…”
@pquentin · 2023-01-12 · confirmation · source
“Have you tried doing the same things with plain sockets? This would probably help understanding the issue better.”
@pquentin · 2023-01-11 · source
“@pquentin I'm not sure what you mean by "the same things."”
@eli-darkly · 2023-01-11 · source

Failure Signature (Search String)

  • trying to close a response hangs if a blocking read is happening on another thread
  • I hoped that closing the response would cause the underlying socket to be closed, causing the client thread to get a read error and terminate. For this demo app, the output would
Copy-friendly signature
signature.txt
Failure Signature ----------------- trying to close a response hangs if a blocking read is happening on another thread I hoped that closing the response would cause the underlying socket to be closed, causing the client thread to get a read error and terminate. For this demo app, the output would look like this:

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- trying to close a response hangs if a blocking read is happening on another thread I hoped that closing the response would cause the underlying socket to be closed, causing the client thread to get a read error and terminate. For this demo app, the output would look like this:

Minimal Reproduction

repro.py
main [MainThread] starting server server [Thread-1] listening on port 10000 main [MainThread] starting client client [Thread-2] opening connection main [MainThread] sleeping a while server [Thread-1] starting stream 127.0.0.1 - - [05/Jan/2023 13:38:11] "GET / HTTP/1.1" 200 - server [Thread-1] wrote 10 bytes client [Thread-2] reading data client [Thread-2] read 10 bytes main [MainThread] about to close response main [MainThread] closed response client [Thread-2] failed: <some kind of I/O error> client [Thread-2] no longer reading main [MainThread] about to clear connection pool main [MainThread] cleared connection pool main [MainThread] exiting

Environment

  • Python: 3.7.13
  • urllib3: 1.26.13

What Broke

The application hangs indefinitely when attempting to close a response while another thread is reading data.

Fix Options (Details)

Option A — Upgrade to fixed release Safe default (recommended)

pip install urllib3==2.3.0

When NOT to use: This fix should not be used if the application requires blocking reads to complete before closing.

Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.

Fix reference: https://github.com/urllib3/urllib3/pull/3527

First fixed release: 2.3.0

Last verified: 2026-02-09. Validate in your environment.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • This fix should not be used if the application requires blocking reads to complete before closing.

Verify Fix

verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.

Did This Fix Work in Your Case?

Quick signal helps us prioritize which fixes to verify and improve.

Prevention

  • Add a CI check that diffs key outputs after upgrades (OpenAPI schema snapshots, JSON payload shapes, CLI output).
  • Upgrade behind a canary and run integration tests against the canary before 100% rollout.
  • Add a stress test that runs high-concurrency workloads and fails on thread dumps / blocked locks.
  • Enable watchdog dumps in prod (faulthandler, thread dump endpoint) to capture deadlocks quickly.

Version Compatibility Table

VersionStatus
2.3.0 Fixed

Related Issues

No related fixes found.

Sources

We don’t republish the full GitHub discussion text. Use the links above for context.