The Fix
pip install redis==7.1.0
Based on closed redis/redis-py issue #2717 · 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%.
@@ -778,20 +778,22 @@ def on_connect(self):
"Disconnects from the Redis server"
self._parser.on_disconnect()
- if self._sock is None:
+
+ conn_sock = self._sock
from redis.asyncio import Redis
import asyncio
redis_client = Redis()
async def redis_subscribe():
async with redis_client.pubsub() as pubsub:
pubsub.subscribe("channel")
async for message in pubsub.listen():
print(message)
task = asyncio.create_task(redis_subscribe())
asyncio.sleep(5)
task.cancel()
asyncio.sleep(5)
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\npip install redis==7.1.0\nWhen NOT to use: This fix is not applicable if the application relies on the previous behavior of the pubsub task.\n\n
Why This Fix Works in Production
- Trigger: Task exception was never retrieved
- Mechanism: A race condition during disconnection leads to a ConnectionError when cancelling a pubsub task
- Why the fix works: Fixes a potential race condition during disconnection that could lead to an AttributeError when the disconnect function is called in parallel. (first fixed release: 7.1.0).
- 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.10.10 in real deployments (not just unit tests).
- A race condition during disconnection leads to a ConnectionError when cancelling a pubsub task
- Surfaces as: Task exception was never retrieved
Proof / Evidence
- GitHub issue: #2717
- Fix PR: https://github.com/redis/redis-py/pull/2719
- First fixed release: 7.1.0
- Reproduced locally: No (not executed)
- Last verified: 2026-02-07
- Confidence: 0.75
- 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 was able to reproduce the issue in the reported version (4.5.4). However, it seems to be fixed in the latest versions — I could…”
“See https://github.com/redis/redis-py/pull/2666#issuecomment-1514452720 for the explanation why this happens. PR https://github.com/redis/redis-py/pull/2719 would potentially fix this.”
“@agronholm I don't think #2719 will fix it because it fixes the sync connection and this issue is in the async connection (maybe #2695 will…”
“@cosminacho Can you confirm that the issue solved in #2695?”
Failure Signature (Search String)
- Task exception was never retrieved
Error Message
Stack trace
Error Message
-------------
Task exception was never retrieved
future: <Task finished name='Task-27' coro=<Retry.call_with_retry() done, defined at redis/asyncio/retry.py:46> exception=ConnectionError('Connection closed by server.')>
Traceback (most recent call last):
File "redis/asyncio/retry.py", line 62, in call_with_retry
await fail(error)
File "redis/asyncio/client.py", line 779, in _disconnect_raise_connect
raise error
File "redis/asyncio/retry.py", line 59, in call_with_retry
return await do()
File "redis/asyncio/client.py", line 784, in _try_execute
return await command(*arg, **kwargs)
File "redis/asyncio/connection.py", line 840, in read_response
response = await self._parser.read_response(
File "redis/asyncio/connection.py", line 413, in read_response
await self.read_from_socket()
File "redis/asyncio/connection.py", line 396, in read_from_socket
raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) from None
redis.exceptions.ConnectionError: Connection closed by server.
Minimal Reproduction
from redis.asyncio import Redis
import asyncio
redis_client = Redis()
async def redis_subscribe():
async with redis_client.pubsub() as pubsub:
pubsub.subscribe("channel")
async for message in pubsub.listen():
print(message)
task = asyncio.create_task(redis_subscribe())
asyncio.sleep(5)
task.cancel()
asyncio.sleep(5)
Environment
- Python: 3.10.10
What Broke
Cancelling a pubsub task results in unhandled ConnectionError exceptions, disrupting message processing.
Why It Broke
A race condition during disconnection leads to a ConnectionError when cancelling a pubsub task
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install redis==7.1.0
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/redis/redis-py/pull/2719
First fixed release: 7.1.0
Last verified: 2026-02-07. Validate in your environment.
When NOT to Use This Fix
- This fix is not applicable if the application relies on the previous behavior of the pubsub task.
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.
Version Compatibility Table
| Version | Status |
|---|---|
| 7.1.0 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.