redis/redis-py · error · SlaveNotFoundError

No slave found for {self.service_name!r}

Error message

No slave found for {self.service_name!r}

What it means

Raised as SlaveNotFoundError from SentinelConnectionPool.rotate_slaves (redis/asyncio/sentinel.py:170) when Sentinel reports zero alive replicas for the service and master discovery also yields nothing (MasterNotFoundError is swallowed). The round-robin replica balancer has exhausted every option, so a read against a slave_for(...) client cannot be served.

Source

Thrown at redis/asyncio/sentinel.py:170

                await self.disconnect(inuse_connections=False)
        return master_address

    async def rotate_slaves(self) -> AsyncIterator:
        """Round-robin slave balancer"""
        slaves = await self.sentinel_manager.discover_slaves(self.service_name)
        if slaves:
            if self.slave_rr_counter is None:
                self.slave_rr_counter = random.randint(0, len(slaves) - 1)
            for _ in range(len(slaves)):
                self.slave_rr_counter = (self.slave_rr_counter + 1) % len(slaves)
                slave = slaves[self.slave_rr_counter]
                yield slave
        # Fallback to the master connection
        try:
            yield await self.get_master_address()
        except MasterNotFoundError:
            pass
        raise SlaveNotFoundError(f"No slave found for {self.service_name!r}")

    def rotate_replicas(self) -> AsyncIterator:
        """Round-robin replica balancer.

        This is an alias for :py:meth:`rotate_slaves`,
        using the preferred Redis 5.0+ terminology.
        """
        return self.rotate_slaves()


class Sentinel(AsyncSentinelCommands):
    """
    Redis Sentinel cluster client

    >>> from redis.sentinel import Sentinel
    >>> sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
    >>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
    >>> await master.set('foo', 'bar')

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Allow the read to fall back to the master (rotate_slaves already tries master discovery; ensure discover_master can succeed).
  2. Scale/restore replica nodes so Sentinel reports at least one healthy replica.
  3. Retry with backoff during transient replica unavailability.

Example fix

# before
val = await slave.get('k')  # SlaveNotFoundError if no replicas
# after
try:
    val = await slave.get('k')
except SlaveNotFoundError:
    val = await master.get('k')  # graceful fallback
Defensive patterns

Strategy: fallback

Validate before calling

replicas = await sentinel.discover_slaves(service_name)
if not replicas:
    use_master_fallback = True

Try / catch

from redis.sentinel import SlaveNotFoundError
try:
    return await slave_client.get(key)
except SlaveNotFoundError:
    return await master_client.get(key)

Prevention

When it happens

Trigger: Calling a read command on a slave_for(...) client when all replicas are in SDOWN/ODOWN or none are configured; replicas removed from the topology while reads are in flight.

Common situations: All replicas down or under maintenance; a single-node deployment with no replicas used with slave_for; failover window where replicas have not yet been promoted/reported.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/5521474ad685bffa.json. Report an issue: GitHub.