redis/redis-py · warning · ConnectionError
The previous master is now a slave
Error message
The previous master is now a slave
What it means
Raised as a ConnectionError inside SentinelManagedConnection.read_response when a ReadOnlyError is received on a connection the pool believes is the master. A ReadOnlyError from a node we think is master means a failover demoted it; the code disconnects so the next connect() re-queries Sentinel for the new master. This is a transient, self-healing failover signal rather than a permanent fault.
Solutions
- Retry the command — the disconnect forces re-discovery of the new master on the next attempt.
- Wrap writes in a retry loop that catches ConnectionError and re-issues the command on a fresh client/connection.
- Tune Sentinel/health-check intervals so failover detection happens faster and connections refresh sooner.
Example fix
# before
await master_client.set("k", "v") # may raise after failover
# after
for attempt in range(3):
try:
await master_client.set("k", "v")
break
except ConnectionError:
await asyncio.sleep(0.5) Defensive patterns
Strategy: retry
Try / catch
from redis.exceptions import ConnectionError
for attempt in range(retries):
try:
return await master_client.execute_command(*args)
except ConnectionError as e:
if "previous master is now a slave" in str(e):
await asyncio.sleep(backoff)
continue
raise Prevention
- Always retry writes on sentinel master clients to absorb failover transients.
- Keep socket_timeout short so stale connections fail fast and re-discover.
When it happens
Trigger: Sending any command through a sentinel master_for() client after a Sentinel-initiated failover has demoted the node we are connected to, before the pool has rediscovered the new master. The server replies READONLY error, triggering this branch because connection_pool.is_master is True.
Common situations: Sentinel failover in progress or recently completed. Long-lived connections holding onto a stale master. Network partition that caused a demotion. Running writes during/just after a failover window.
Related errors
- No slave found for
- The previous master is now a slave
- Bad response from PING health check
- Buffer is closed.
- Cannot enable maintenance notifications for connection…
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/ebde22b441ce352a.
Report an issue: GitHub.
Appendix: source
Thrown at redis/asyncio/sentinel.py:94
disconnect_on_error: Optional[float] = True,
push_request: Optional[bool] = False,
):
try:
return await super().read_response(
disable_decoding=disable_decoding,
timeout=timeout,
disconnect_on_error=disconnect_on_error,
push_request=push_request,
)
except ReadOnlyError:
if self.connection_pool.is_master:
# When talking to a master, a ReadOnlyError when likely
# indicates that the previous master that we're still connected
# to has been demoted to a slave and there's a new master.
# calling disconnect will force the connection to re-query
# sentinel during the next connect() attempt.
await self.disconnect()
raise ConnectionError("The previous master is now a slave")
raise
class SentinelManagedSSLConnection(SentinelManagedConnection, SSLConnection):
pass
class SentinelConnectionPool(ConnectionPool):
"""
Sentinel backed connection pool.
If ``check_connection`` flag is set to True, SentinelManagedConnection
sends a PING command right after establishing the connection.
"""
def __init__(self, service_name, sentinel_manager, **kwargs):
kwargs["connection_class"] = kwargs.get(
"connection_class",View on GitHub (pinned to 6a6b581b48)