Jump to solution
Verify

The Fix

Upgrade to version 0.13.0 or later.

Based on closed encode/httpx issue #2047 · PR/commit linked

Production note: This tends to surface only under concurrency. Reproduce with load tests and watch for lock contention/cancellation paths.

Jump to Verify Open PR/Commit
@@ -158,17 +158,6 @@ def test_empty_http_version(): -def test_timeout_repr(): - timeout = httpx.TimeoutConfig(timeout=5.0) - assert repr(timeout) == "TimeoutConfig(timeout=5.0)"
repro.py
import httpx import trio async def download(client, url): print("started download") response = await client.get(url) print(response) async def close_client(client): await trio.sleep(1) print("close client") await client.aclose() async def main(): async with httpx.AsyncClient() as client: async with trio.open_nursery() as nursery: nursery.start_soon(download, client, "https://speed.hetzner.de/100MB.bin") nursery.start_soon(close_client, client) trio.run(main)
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\nUpgrade to version 0.13.0 or later.\nWhen NOT to use: This fix should not be applied if the application does not handle high concurrency.\n\n

Why This Fix Works in Production

  • Trigger: response = await self.ref_client.get_ticker_details_v3(stock, date)
  • Mechanism: The issue arises from improper handling of concurrent requests leading to a ValueError
  • Why the fix works: Reorganizes timeout config tests and adds new tests for default cases, which may help address issues related to high concurrency in httpx. (first fixed release: 0.13.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

  • Triggered by an upgrade/regression window: 3.7–3.8 breaks; 0.13.0 is the first fixed release.
  • Shows up under Python 3.8 in real deployments (not just unit tests).
  • The issue arises from improper handling of concurrent requests leading to a ValueError
  • Surfaces as: Traceback (most recent call last):

Proof / Evidence

  • GitHub issue: #2047
  • Fix PR: https://github.com/encode/httpcore/pull/491
  • First fixed release: 0.13.0
  • Affected versions: 3.7–3.8
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-08
  • Confidence: 0.85
  • Did this fix it?: Yes (upstream fix exists)
  • Own content ratio: 0.29

Discussion

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

“That's a great observation, thanks @aworkin. I think the sensible tack there is to inherit BaseException instead of Exception. (Pretty reasonable for resource-closing actions, anyways)”
@lovelydinosaur · 2022-01-27 · confirmation · source
“For reference, a version of what I saw that triggered this is here: https://github.com/encode/httpx/discussions/2043#discussioncomment-2050790”
@ahopkins · 2022-01-26 · source
“Here's an example that'll raise the same traceback... Which results in...”
@lovelydinosaur · 2022-01-27 · source
“@ahopkins - I've got https://github.com/encode/httpcore/pull/491 to resolve this now”
@lovelydinosaur · 2022-01-27 · source

Failure Signature (Search String)

  • response = await self.ref_client.get_ticker_details_v3(stock, date)

Error Message

Stack trace
error.txt
Error Message ------------- Traceback (most recent call last): File "/home/pssolanki/projects/tests/lib_test/test.py", line 86, in get_market_cap response = await self.ref_client.get_ticker_details_v3(stock, date) File "/home/pssolanki/projects/openSource/polygon/polygon/reference_apis/reference_api.py", line 875, in get_ticker_details_v3 _res = await self._get_response(_path, params=_data) File "/home/pssolanki/projects/openSource/polygon/polygon/base_client.py", line 240, in _get_response _res = await self.session.request('GET', self.BASE + path, params=params) File "/home/pssolanki/projects/tests/lib_test/venv/lib/python3.8/site-packages/httpx/_client.py", line 1513, in request return await self.send(request, auth=auth, follow_redirects=follow_redirects) File "/home/pssolanki/projects/tests/lib_test/venv/lib/python3.8/site-packages/httpx/_client.py", line 1614, in send raise exc File "/home/pssolanki/projects/tests/lib_test/venv/lib/python3.8/site-packages/httpx/_client.py", line 1608, in send await response.aread() File "/home/pssolanki/projects/tests/lib_test/venv/lib/python3.8/site-packages/httpx/_models.py", line 1662, in aread self._content = b"".join([part async for part in self.aiter_bytes()]) File "/home/pssolanki/projects/tests/lib_test/venv/lib/python3.8/site-packages/httpx/_models.py", line 1662, in <listcomp> self._content = b"".join([part asy ... (truncated) ...
Stack trace
error.txt
Error Message ------------- python example.py started download close_client Traceback (most recent call last): File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 1601, in send await response.aread() File "/Users/tomchristie/GitHub/encode/httpx/httpx/_models.py", line 1662, in aread self._content = b"".join([part async for part in self.aiter_bytes()]) File "/Users/tomchristie/GitHub/encode/httpx/httpx/_models.py", line 1662, in <listcomp> self._content = b"".join([part async for part in self.aiter_bytes()]) File "/Users/tomchristie/GitHub/encode/httpx/httpx/_models.py", line 1678, in aiter_bytes async for raw_bytes in self.aiter_raw(): File "/Users/tomchristie/GitHub/encode/httpx/httpx/_models.py", line 1732, in aiter_raw async for raw_stream_bytes in self.stream: File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 145, in __aiter__ async for chunk in self._stream: File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 239, in __aiter__ async for part in self._httpcore_stream: File "/Users/tomchristie/GitHub/encode/httpx/venv/lib/python3.7/site-packages/httpcore/_async/connection_pool.py", line 328, in __aiter__ async for part in self._stream: File "/Users/tomchristie/GitHub/encode/httpx/venv/lib/python3.7/site-packages/httpcore/_async/http11.py", line 286, in __aiter__ async for chunk in sel ... (truncated) ...

Minimal Reproduction

repro.py
import httpx import trio async def download(client, url): print("started download") response = await client.get(url) print(response) async def close_client(client): await trio.sleep(1) print("close client") await client.aclose() async def main(): async with httpx.AsyncClient() as client: async with trio.open_nursery() as nursery: nursery.start_soon(download, client, "https://speed.hetzner.de/100MB.bin") nursery.start_soon(close_client, client) trio.run(main)

Environment

  • Python: 3.8

What Broke

Users experience ValueErrors when making multiple concurrent requests, causing disruptions.

Why It Broke

The issue arises from improper handling of concurrent requests leading to a ValueError

Fix Options (Details)

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

Upgrade to version 0.13.0 or later.

When NOT to use: This fix should not be applied if the application does not handle high concurrency.

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

Fix reference: https://github.com/encode/httpcore/pull/491

First fixed release: 0.13.0

Last verified: 2026-02-08. 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 applied if the application does not handle high concurrency.

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
3.7 Broken
3.8 Broken
0.13.0 Fixed

Related Issues

No related fixes found.

Sources

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