redis/redis-py · warning · UnhealthyDatabaseException

Unhealthy database

Error message

Unhealthy database

What it means

Raised by `AbstractHealthCheckPolicy.execute()` (redis/asyncio/multidb/healthcheck.py:156) as UnhealthyDatabaseException when any individual health check (wrapped in `execute_with_timeout`) returns an Exception — including `asyncio.TimeoutError` if the probe exceeds its `health_check_timeout`. The exception carries `.database` and `.original_exception`, and the caller (`_check_databases_health`) uses it to force the database's circuit to OPEN.

Source

Thrown at redis/asyncio/multidb/healthcheck.py:156

        # Create wrapper tasks that apply individual timeouts
        async def execute_with_timeout(health_check: HealthCheck):
            return await asyncio.wait_for(
                self._execute(health_check, database),
                timeout=health_check.health_check_timeout,
            )

        # Run all health checks concurrently and collect results/exceptions
        results = await asyncio.gather(
            *[execute_with_timeout(hc) for hc in health_checks],
            return_exceptions=True,
        )

        # Check results - handle exceptions and failures
        for result in results:
            if isinstance(result, Exception):
                # Any exception (including TimeoutError) makes the database unhealthy
                raise UnhealthyDatabaseException("Unhealthy database", database, result)
            elif not result:
                # Health check returned False
                return False

        return True

    async def get_client(self, database) -> AsyncRedisClientT:
        """
        Get or create a health check client for the database.

        Creates a single client instance per database that follows topology
        changes automatically. For cluster databases, the client handles
        node discovery and slot mapping internally.
        """
        db_id = id(database)
        client = self._clients.get(db_id)

        if client is None:

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Increase `health_check_timeout` and/or `health_check_probes` in MultiDbConfig so transient slowness does not trip the check.
  2. Inspect `exc.original_exception` (and the logger.debug at client.py:382-385) for the root cause.
  3. Use a more lenient policy (`HealthCheckPolicies.HEALTHY_MAJORITY` or `HEALTHY_ANY`) so a single failing probe/check does not mark the DB unhealthy.
  4. Fix the underlying connectivity/auth/TLS issue causing the probe exception.

Example fix

# before
cfg = MultiDbConfig(
    databases_config=[db],
    health_check_timeout=1,  # too tight
)

# after
from redis.asyncio.multidb.healthcheck import HealthCheckPolicies
cfg = MultiDbConfig(
    databases_config=[db],
    health_check_timeout=5,
    health_check_probes=5,
    health_check_policy=HealthCheckPolicies.HEALTHY_MAJORITY,
)
Defensive patterns

Strategy: try-catch

Validate before calling

from redis.multidb.circuit import State as CBState

async def db_likely_healthy(client, database) -> bool:
    try:
        await client._check_db_health(database)
        return database.circuit.state == CBState.CLOSED
    except Exception:
        return False

Type guard

from redis.multidb.exception import UnhealthyDatabaseException

def is_unhealthy_db_exception(exc) -> bool:
    return isinstance(exc, UnhealthyDatabaseException)

Try / catch

from redis.multidb.exception import UnhealthyDatabaseException

try:
    await client.set('k','v')
except UnhealthyDatabaseException as e:
    # e.database is the failing DB, e.original_exception is the root cause
    logger.warning('DB %s unhealthy: %r', e.database, e.original_exception)
    # failover layer will pick another DB; or shed load

Prevention

When it happens

Trigger: A health-check probe throwing any exception: PING returning a connection error, a probe exceeding `health_check_timeout` (default 3s), a LagAwareHealthCheck REST call failing, etc. Triggered during both initial and recurring health checks.

Common situations: Network blip making PING time out; Redis briefly unresponsive under load; LagAwareHealthCheck REST API unreachable; health_check_timeout too low for slow networks; TLS handshake failures during the probe.

Related errors


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