The Fix
Upgrade to version 0.11.4 or later.
Based on closed Kludex/uvicorn issue #111 · PR/commit linked
Production note: Watch p95/p99 latency and retry volume; timeouts can turn into retry storms and duplicate side-effects.
@@ -340,6 +340,17 @@ async def __call__(self, receive, send):
[email protected]("protocol_cls", [HttpToolsProtocol, H11Protocol])
+def test_early_disconnect(protocol_cls):
+ def app(scope):
ERROR: Exception in callback UVTransport._call_connection_lost
handle: <Handle UVTransport._call_connection_lost>
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/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 "uvloop/cbhandles.pyx", line 70, in uvloop.loop.Handle._run
File "uvloop/handles/basetransport.pyx", line 202, in uvloop.loop.UVBaseTransport._call_connection_lost
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 79, in connection_lost
self.conn.send(event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 464, in send
data_list = self.send_with_data_passthrough(event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 490, in send_with_data_passthrough
self._process_event(self.our_role, event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 238, in _process_event
self._cstate.process_event(role, type(event), server_switch_event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_state.py", line 238, in process_event
self._fire_event_triggered_transitions(role, event_type)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_state.py", line 253, in _fire_event_triggered_transitions
.format(event_type, role, self.states[role]))
h11._util.LocalProtocolError: can't handle event type <class 'h11._events.ConnectionClosed'> for SERVER in state SEND_BODY
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 171, in run_asgi
result = await asgi(self.receive, self.send)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 190, in __call__
await self.handle(body)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__
return await asyncio.wait_for(future, timeout=None)
File "/usr/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
return (yield from fut)
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler
return self.func(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 229, in handle
self.send(response_message)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__
return call_result.result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 261, in send
output = protocol.conn.send(event
... (truncated) ...
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.11.4 or later.\nWhen NOT to use: Do not apply this fix if the application requires strict connection handling.\n\n
Why This Fix Works in Production
- Trigger: ERROR: Exception in ASGI application
- Mechanism: RuntimeError occurs when attempting to send a response after the connection has been closed
- Why the fix works: Addresses a RuntimeError in uvicorn by preventing logging errors on early disconnects. (first fixed release: 0.11.4).
- 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.6 in real deployments (not just unit tests).
- RuntimeError occurs when attempting to send a response after the connection has been closed
- Surfaces as: ERROR: Exception in ASGI application
Proof / Evidence
- GitHub issue: #111
- Fix PR: https://github.com/kludex/uvicorn/pull/114
- First fixed release: 0.11.4
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.85
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.16
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Looks like it's a case when sending a response and the connection has closed prematurely. Might be resolved by if self.disconnected: return at the start…”
“could you do 2 things please to try nail that down, 1”
“FYI I am getting this error with uvicorn 0.11.5 and h11 0.9.0, on a Django channels project”
“I am not sure how to reproduce. In one project it is happening for every 5 requests or so and it is failing randomly. In…”
Failure Signature (Search String)
- ERROR: Exception in ASGI application
Error Message
Stack trace
Error Message
-------------
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/httptools.py", line 196, in run_asgi
result = await asgi(self.receive, self.send)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 190, in __call__
await self.handle(body)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__
return await asyncio.wait_for(future, timeout=None)
File "/usr/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
return (yield from fut)
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler
return self.func(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 229, in handle
self.send(response_message)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__
return call_result.result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_
... (truncated) ...
Stack trace
Error Message
-------------
ERROR: Exception in callback UVTransport._call_connection_lost
handle: <Handle UVTransport._call_connection_lost>
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/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 "uvloop/cbhandles.pyx", line 70, in uvloop.loop.Handle._run
File "uvloop/handles/basetransport.pyx", line 202, in uvloop.loop.UVBaseTransport._call_connection_lost
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 79, in connection_lost
self.conn.send(event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 464, in send
data_list = self.send_with_data_passthrough(event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 490, in send_with_data_passthrough
self._process_event(self.our_role, event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 238, in _process_event
self._cstate.process_event(role, type(event), server_switch_event)
File "/home/chillar/.virtual
... (truncated) ...
Stack trace
Error Message
-------------
ERROR: Exception in callback H11Protocol.timeout_keep_alive_handler()
handle: <TimerHandle when=112443.109 H11Protocol.timeout_keep_alive_handler()>
Traceback (most recent call last):
File "c:\otree\ve38\lib\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 "C:\Users\wicke\AppData\Local\Programs\Python\Python38\lib\asyncio\events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "c:\otree\ve38\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 339, in timeout_keep_alive_handler
self.conn.send(event)
File "c:\otree\ve38\lib\site-packages\h11\_connection.py", line 469, in send
data_list = self.send_with_data_passthrough(event)
File "c:\otree\ve38\lib\site-packages\h11\_connection.py", line 494, in send_with_data_passthrough
self._process_event(self.our_role, event)
File "c:\otree\ve38\lib\site-packages\h11\_connection.py", line 242, in _process_event
self._cstate.process_event(role, type(event), server_switch_event)
File "c:\otree\ve38\lib\site-packages\h11\_state.py", line 238, in process_event
self._fire_event_triggered_transitions(role, event_type)
Fil
... (truncated) ...
Minimal Reproduction
ERROR: Exception in callback UVTransport._call_connection_lost
handle: <Handle UVTransport._call_connection_lost>
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/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 "uvloop/cbhandles.pyx", line 70, in uvloop.loop.Handle._run
File "uvloop/handles/basetransport.pyx", line 202, in uvloop.loop.UVBaseTransport._call_connection_lost
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 79, in connection_lost
self.conn.send(event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 464, in send
data_list = self.send_with_data_passthrough(event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 490, in send_with_data_passthrough
self._process_event(self.our_role, event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_connection.py", line 238, in _process_event
self._cstate.process_event(role, type(event), server_switch_event)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_state.py", line 238, in process_event
self._fire_event_triggered_transitions(role, event_type)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/h11/_state.py", line 253, in _fire_event_triggered_transitions
.format(event_type, role, self.states[role]))
h11._util.LocalProtocolError: can't handle event type <class 'h11._events.ConnectionClosed'> for SERVER in state SEND_BODY
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 171, in run_asgi
result = await asgi(self.receive, self.send)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 190, in __call__
await self.handle(body)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__
return await asyncio.wait_for(future, timeout=None)
File "/usr/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
return (yield from fut)
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler
return self.func(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 229, in handle
self.send(response_message)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__
return call_result.result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/h11.py", line 261, in send
output = protocol.conn.send(event
... (truncated) ...
Environment
- Python: 3.6
What Broke
Some requests fail with a RuntimeError, causing intermittent application errors.
Why It Broke
RuntimeError occurs when attempting to send a response after the connection has been closed
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.11.4 or later.
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/kludex/uvicorn/pull/114
First fixed release: 0.11.4
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not apply this fix if the application requires strict connection handling.
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
- Make timeouts explicit and test them (unit + integration) to avoid silent behavior changes.
- Instrument retries (attempt count + reason) and alert on spikes to catch dependency slowdowns.
Version Compatibility Table
| Version | Status |
|---|---|
| 0.11.4 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.