The Fix
Fix improperly closed WebSocket connections generating a backtrace.
Based on closed aio-libs/aiohttp issue #9880 · 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%.
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+Fixed improperly closed WebSocket connections generating an unhandled exception -- by :user:`bdraco`.
diff --git a/aiohttp/_websocket/reader_py.py b/aiohttp/_websocket/reader_py.py
index 04d654f8bf3..aa4b6ba2704 100644
AttributeError: 'aiohttp._websocket.reader_c.WebSocketDataQueue' object has no attribute 'is_eof'
^^^^^^^^^^^^^^^^^^^^
or (self._payload is not None and not self._payload.is_eof())
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/client_proto.py", line 55, in should_close
^^^^^^^^^^^^^^^^^^^^^
if self._force_close or should_close or protocol.should_close:
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/connector.py", line 705, in _release
self._connector._release(self._key, self._protocol)
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/connector.py", line 197, in release
self._connection.release()
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/client_reqrep.py", line 945, in __del__
Traceback (most recent call last):
Exception ignored in: <function ClientResponse.__del__ at 0x7faf9467ff60>
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Apply the official fix\nFix improperly closed WebSocket connections generating a backtrace.\nWhen NOT to use: This fix should not be applied if the WebSocket connections are managed correctly.\n\n
Why This Fix Works in Production
- Trigger: AttributeError: 'aiohttp._websocket.reader_c.WebSocketDataQueue' object has no attribute 'is_eof'
- Mechanism: The WebSocketDataQueue class lacked an is_eof method, causing an AttributeError during cleanup
- 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.12 in real deployments (not just unit tests).
- The WebSocketDataQueue class lacked an is_eof method, causing an AttributeError during cleanup
- Surfaces as: AttributeError: 'aiohttp._websocket.reader_c.WebSocketDataQueue' object has no attribute 'is_eof'
Proof / Evidence
- GitHub issue: #9880
- Fix PR: https://github.com/aio-libs/aiohttp/pull/9883
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.80
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.36
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Its likely something isn't closing the WebSocket connections and they are only getting cleaned up in garbage collection. Likely after cancellation in your case from…”
“Oh one important note: this was definitely not happening on 3.10.10”
“Looks like we don’t have a test for this case. Should be an easy fix”
“Thanks for including the full trace in the initial report”
Failure Signature (Search String)
- AttributeError: 'aiohttp._websocket.reader_c.WebSocketDataQueue' object has no attribute 'is_eof'
Error Message
Stack trace
Error Message
-------------
AttributeError: 'aiohttp._websocket.reader_c.WebSocketDataQueue' object has no attribute 'is_eof'
^^^^^^^^^^^^^^^^^^^^
or (self._payload is not None and not self._payload.is_eof())
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/client_proto.py", line 55, in should_close
^^^^^^^^^^^^^^^^^^^^^
if self._force_close or should_close or protocol.should_close:
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/connector.py", line 705, in _release
self._connector._release(self._key, self._protocol)
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/connector.py", line 197, in release
self._connection.release()
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/client_reqrep.py", line 945, in __del__
Traceback (most recent call last):
Exception ignored in: <function ClientResponse.__del__ at 0x7faf9467ff60>
Minimal Reproduction
AttributeError: 'aiohttp._websocket.reader_c.WebSocketDataQueue' object has no attribute 'is_eof'
^^^^^^^^^^^^^^^^^^^^
or (self._payload is not None and not self._payload.is_eof())
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/client_proto.py", line 55, in should_close
^^^^^^^^^^^^^^^^^^^^^
if self._force_close or should_close or protocol.should_close:
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/connector.py", line 705, in _release
self._connector._release(self._key, self._protocol)
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/connector.py", line 197, in release
self._connection.release()
File "/home/appuser/.venv/lib/python3.12/site-packages/aiohttp/client_reqrep.py", line 945, in __del__
Traceback (most recent call last):
Exception ignored in: <function ClientResponse.__del__ at 0x7faf9467ff60>
Environment
- Python: 3.12
What Broke
Closing a WebSocket connection resulted in unhandled exceptions logged in production.
Why It Broke
The WebSocketDataQueue class lacked an is_eof method, causing an AttributeError during cleanup
Fix Options (Details)
Option A — Apply the official fix
Fix improperly closed WebSocket connections generating a backtrace.
Fix reference: https://github.com/aio-libs/aiohttp/pull/9883
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix should not be applied if the WebSocket connections are managed correctly.
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
- Capture the exact failing error string in logs and tests so you can reproduce via a minimal script.
- Pin production dependencies and upgrade only with a reproducible test that hits the failing path.
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.