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.
@@ -50,26 +50,3 @@ async def __aexit__(
) -> None:
await self.close()
-
-
-class OpenConnection:
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)
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
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).
- 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…”
“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…”
“Hi @iwoloschin! A minimal reproduction example might be useful, indeed! At first glance it seems like a race condition”
“The issue was worse at 0.9.5, a failed request would hang/kill the entire task”
Failure Signature (Search String)
- return await self.request(
Error Message
Stack trace
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
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.
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.
When NOT to Use This Fix
- This fix is not suitable for scenarios requiring the `OpenConnection` abstraction.
Verify Fix
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
| Version | Status |
|---|---|
| 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.