The Fix
Upgrade to version 0.7.3 or later.
Based on closed encode/httpx issue #327 · PR/commit linked
Production note: Watch p95/p99 latency and retry volume; timeouts can turn into retry storms and duplicate side-effects.
@@ -81,7 +81,7 @@ def __init__(
dispatch = WSGIDispatch(app=app)
else:
- dispatch = ASGIDispatch(app=app)
+ dispatch = ASGIDispatch(app=app, backend=backend)
# client.py
import asyncio
import httpx
async def main():
url = "http://localhost:8000"
async with httpx.ConnectionPool() as http:
response = await http.request("GET", url)
await response.read()
input("Shutdown the server to close the keep-alive connection")
response = await http.request("GET", url)
await response.read()
assert len(http.active_connections) == 0
assert len(http.keepalive_connections) == 1
asyncio.run(main())
Re-run: python debugflorimond/client.py
Option A — Upgrade to fixed release\nUpgrade to version 0.7.3 or later.\nWhen NOT to use: This fix is not applicable if the application does not use the trio concurrency backend.\n\n
Why This Fix Works in Production
- Trigger: $ python debugflorimond/client.py
- Mechanism: Improper teardown of connections leads to h11 state being scrambled after a ConnectionResetError
- Why the fix works: Adds a trio concurrency backend to the HTTPX client, addressing issues with connection handling when the remote server goes down. (first fixed release: 0.7.3).
- If left unfixed, tail latency can spike under load and surface as timeouts/retries (amplifying incident impact).
Why This Breaks in Prod
- Shows up under Python 3.7 in real deployments (not just unit tests).
- Improper teardown of connections leads to h11 state being scrambled after a ConnectionResetError
- Surfaces as: $ python debugflorimond/client.py
Proof / Evidence
- GitHub issue: #327
- Fix PR: https://github.com/encode/httpx/pull/276
- First fixed release: 0.7.3
- 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.38
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“OK, nevermind”
Failure Signature (Search String)
- $ python debugflorimond/client.py
Error Message
Stack trace
Error Message
-------------
$ python debugflorimond/client.py
Shutdown the server to close the keep-alive connection
Traceback (most recent call last):
File "/Users/florimond/Developer/python-projects/httpx/venv/lib/python3.7/site-packages/h11/_state.py", line 249, in _fire_event_triggered_transitions
new_state = EVENT_TRIGGERED_TRANSITIONS[role][state][event_type]
KeyError: <class 'h11._events.ConnectionClosed'>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "debugflorimond/client.py", line 20, in <module>
asyncio.run(main())
File "/Users/florimond/.pyenv/versions/3.7.3/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/Users/florimond/.pyenv/versions/3.7.3/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "debugflorimond/client.py", line 14, in main
response = await http.request("GET", url)
File "/Users/florimond/Developer/python-projects/httpx/httpx/dispatch/base.py", line 40, in request
return await self.send(request, verify=verify, cert=cert, timeout=timeout)
File "/Users/florimond/Developer/python-projects/httpx/httpx/dispatch/connection_pool.py", line 126, in send
raise exc
File "/Users/florimond/Developer/python-projects/httpx/httpx/dispatch/connection_pool.py", line 121, in send
request, verify=v
... (truncated) ...
Minimal Reproduction
# client.py
import asyncio
import httpx
async def main():
url = "http://localhost:8000"
async with httpx.ConnectionPool() as http:
response = await http.request("GET", url)
await response.read()
input("Shutdown the server to close the keep-alive connection")
response = await http.request("GET", url)
await response.read()
assert len(http.active_connections) == 0
assert len(http.keepalive_connections) == 1
asyncio.run(main())
Environment
- Python: 3.7
What Broke
Clients experience connection errors and improper state after server disconnections.
Why It Broke
Improper teardown of connections leads to h11 state being scrambled after a ConnectionResetError
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.7.3 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/276
First fixed release: 0.7.3
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix is not applicable if the application does not use the trio concurrency backend.
Verify Fix
Re-run: python debugflorimond/client.py
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.7.3 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.