Jump to solution
Verify

The Fix

Upgrade to version 0.13.0 or later.

Based on closed encode/httpx issue #689 · 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
@@ -50,26 +50,3 @@ async def __aexit__( ) -> None: await self.close() - - -class OpenConnection:
repro.py
class GNS3Project: def __init__(self, ...): self.http_client = httpx.AsyncClient() async def provision_router(self, sema, ...): async with sema: # several sequential HTTP operations: put/post/get, e.g.: # await self.http_client.post(url) async def main(): gns3_project = GNS3Project(...) sema = asyncio.BoundedSemaphore(25) tasks = [ asyncio.create_task( gns3_project.provision_router( devices[i], template=router_config_template, sema=sema ) ) for i in range(500, 600) ] await asyncio.gather(*tasks)
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 is not suitable for scenarios requiring the `OpenConnection` abstraction.\n\n

Why This Fix Works in Production

  • Trigger: return await self.request(
  • Mechanism: Dropped the `OpenConnection` abstraction to resolve an AssertionError issue related to connection handling
  • Why the fix works: Dropped the `OpenConnection` abstraction to resolve an AssertionError issue related to connection handling. (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

  • Shows up under Python 3.8 in real deployments (not just unit tests).
  • Dropped the `OpenConnection` abstraction to resolve an AssertionError issue related to connection handling
  • Surfaces as: File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 679, in get

Proof / Evidence

  • GitHub issue: #689
  • Fix PR: https://github.com/encode/httpx/pull/700
  • First fixed release: 0.13.0
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-09
  • Confidence: 0.75
  • Did this fix it?: Yes (upstream fix exists)
  • Own content ratio: 0.39

Discussion

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

“@florimondmanca I keep forgetting about the environmental variables! I didn't see anything obvious with a quick test. Let me see if I can whip up…”
@iwoloschin · 2019-12-28 · repro detail · source
“No luck on making a minimal test here, but I did figure out that it's not only happening on the first connection, sometimes it happens…”
@iwoloschin · 2019-12-28 · repro detail · source
“Hi @iwoloschin! A minimal reproduction example might be useful, indeed! At first glance it seems like a race condition”
@florimondmanca · 2019-12-27 · repro detail · source
“The issue was worse at 0.9.5, a failed request would hang/kill the entire task”
@iwoloschin · 2019-12-30 · source

Failure Signature (Search String)

  • return await self.request(

Error Message

Stack trace
error.txt
Error Message ------------- File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 679, in get return await self.request( File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 259, in request response = await self.send( File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 403, in send response = await self.send_handling_redirects( File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 465, in send_handling_redirects response = await self.send_handling_auth( File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 591, in send_handling_auth response = await self.send_single_request(request, timeout, verify, cert) File "/opt/venv/lib/python3.8/site-packages/httpx/client.py", line 618, in send_single_request response = await dispatcher.send( File "/opt/venv/lib/python3.8/site-packages/httpx/dispatch/connection_pool.py", line 147, in send connection = await self.acquire_connection( File "/opt/venv/lib/python3.8/site-packages/httpx/dispatch/connection_pool.py", line 165, in acquire_connection connection = self.pop_connection(origin) File "/opt/venv/lib/python3.8/site-packages/httpx/dispatch/connection_pool.py", line 215, in pop_connection connection = self.active_connections.pop_by_origin(origin, http2_only=True) File "/opt/venv/lib/python3.8/site-packages/httpx/dispatch/connection_pool.py", line ... (truncated) ...

Minimal Reproduction

repro.py
class GNS3Project: def __init__(self, ...): self.http_client = httpx.AsyncClient() async def provision_router(self, sema, ...): async with sema: # several sequential HTTP operations: put/post/get, e.g.: # await self.http_client.post(url) async def main(): gns3_project = GNS3Project(...) sema = asyncio.BoundedSemaphore(25) tasks = [ asyncio.create_task( gns3_project.provision_router( devices[i], template=router_config_template, sema=sema ) ) for i in range(500, 600) ] await asyncio.gather(*tasks)

Environment

  • Python: 3.8
  • httpx: 0.9.5

What Broke

Unexpected AssertionError during concurrent requests leading to potential task hangs.

Why It Broke

Dropped the `OpenConnection` abstraction to resolve an AssertionError issue related to connection handling

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 is not suitable for scenarios requiring the `OpenConnection` abstraction.

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

Fix reference: https://github.com/encode/httpx/pull/700

First fixed release: 0.13.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 is not suitable for scenarios requiring the `OpenConnection` abstraction.

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
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.