Jump to solution
Verify

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

Jump to Verify Open PR/Commit
@@ -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
repro.py
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)
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\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).
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.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…”
@petyaslavova · 2025-02-04 · confirmation · source
“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 · 2023-04-22 · source
“@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…”
@dvora-h · 2023-05-01 · source
“@cosminacho Can you confirm that the issue solved in #2695?”
@dvora-h · 2023-07-16 · source

Failure Signature (Search String)

  • Task exception was never retrieved

Error Message

Stack trace
error.txt
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

repro.py
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

When NOT to use: This fix is not applicable if the application relies on the previous behavior of the pubsub task.

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.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

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

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

  • 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

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