Jump to solution
Verify

The Fix

Upgrade to version 0.11.4 or later.

Based on closed Kludex/uvicorn issue #56 · PR/commit linked

Production note: Most teams hit this during upgrades or environment changes. Roll out with a canary and smoke critical endpoints (health, OpenAPI/docs) before 100%.

Jump to Verify Open PR/Commit
@@ -1,6 +1,7 @@ httptools uvloop +websockets # Testing
repro.py
async def chat_server(message, channels): """ ASGI-style 'Hello, world' application. """ if message['channel'] == 'websocket.connect': await channels['reply'].send({'accept': True})
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.11.4 or later.\nWhen NOT to use: Do not use if it changes public behavior or if the failure cannot be reproduced.\n\n

Why This Fix Works in Production

  • Trigger: Starting worker [9001] serving at: 0.0.0.0:8000
  • Mechanism: The transfer_data_task variable is not initialized, causing None to be added to the event queue
  • Why the fix works: Adds websocket support for the new ASGI spec, resolving compatibility issues with websockets 4.0.1. (first fixed release: 0.11.4).
Production impact:
  • If left unfixed, the same config can fail only in production (env differences), causing startup failures or partial feature outages.

Why This Breaks in Prod

  • Shows up under Python 3.6 in real deployments (not just unit tests).
  • The transfer_data_task variable is not initialized, causing None to be added to the event queue
  • Surfaces as: Starting worker [9001] serving at: 0.0.0.0:8000

Proof / Evidence

  • GitHub issue: #56
  • Fix PR: https://github.com/kludex/uvicorn/pull/65
  • 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.44

Discussion

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

“I had this same issue working on my fork - using 3.4.0 allowed websockets to work normally.”
@jordaneremieff · 2018-03-27 · source
“Thanks for the confirmation @erm. Hopefully I’ll get back to this given the renewed work on API Star. Bunch of other work I’ll need to…”
@lovelydinosaur · 2018-03-27 · source
“I discovered the issue. The .connection_open() method on the websocket protocol needs to be called after the handshake otherwise the transfer_data_task future isn't assigned and…”
@jordaneremieff · 2018-03-28 · source

Failure Signature (Search String)

  • Starting worker [9001] serving at: 0.0.0.0:8000

Error Message

Stack trace
error.txt
Error Message ------------- Starting worker [9001] serving at: 0.0.0.0:8000 Task exception was never retrieved future: <Task finished coro=<reader() done, defined at /home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/uvicorn/protocols/websocket.py:65> exception=TypeError('An asyncio.Future, a coroutine or an awaitable is required',)> Traceback (most recent call last): File "/home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/uvicorn/protocols/websocket.py", line 72, in reader data = await protocol.recv() File "/home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/websockets/protocol.py", line 309, in recv loop=self.loop, return_when=asyncio.FIRST_COMPLETED) File "/usr/lib/python3.6/asyncio/tasks.py", line 311, in wait fs = {ensure_future(f, loop=loop) for f in set(fs)} File "/usr/lib/python3.6/asyncio/tasks.py", line 311, in <setcomp> fs = {ensure_future(f, loop=loop) for f in set(fs)} File "/usr/lib/python3.6/asyncio/tasks.py", line 526, in ensure_future raise TypeError('An asyncio.Future, a coroutine or an awaitable is ' TypeError: An asyncio.Future, a coroutine or an awaitable is required

Minimal Reproduction

repro.py
async def chat_server(message, channels): """ ASGI-style 'Hello, world' application. """ if message['channel'] == 'websocket.connect': await channels['reply'].send({'accept': True})

Environment

  • Python: 3.6

What Broke

The application raises a TypeError when trying to receive data from the websocket.

Why It Broke

The transfer_data_task variable is not initialized, causing None to be added to the event queue

Fix Options (Details)

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

Upgrade to version 0.11.4 or later.

When NOT to use: Do not use if it changes public behavior or if the failure cannot be reproduced.

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/65

First fixed release: 0.11.4

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

  • Do not use if it changes public behavior or if the failure cannot be reproduced.

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 TLS smoke test that performs a real handshake in CI (include CA bundle validation and hostname checks).
  • Alert on handshake failures by error string and endpoint to catch cert/CA changes quickly.

Version Compatibility Table

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