redis/redis-py · error · TypeError

Unsupported client type: {type(database.client)}

Error message

Unsupported client type: {type(database.client)}

What it means

Raised by `AbstractHealthCheckPolicy.get_client()` (redis/asyncio/multidb/healthcheck.py:213) when `database.client` is not one of the supported types (`AsyncRedis`, `SyncRedis`, `AsyncRedisCluster`, `SyncRedisCluster`). The health-check client builder only knows how to mirror connection kwargs for those four types; anything else (a custom wrapper, a mock, a Sentinel client) is rejected with TypeError.

Source

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

                        nodes_manager,
                        "require_full_coverage",
                        getattr(nodes_manager, "_require_full_coverage", True),
                    )
                    client = AsyncRedisCluster(
                        host=first_node.host,
                        port=first_node.port,
                        dynamic_startup_nodes=nodes_manager._dynamic_startup_nodes,
                        address_remap=nodes_manager.address_remap,
                        require_full_coverage=require_full_coverage,
                        retry=database.client.retry,
                        **filtered_kwargs,
                    )
                else:
                    raise ValueError(
                        "Cluster client has no nodes - cannot create health check client"
                    )
            else:
                raise TypeError(f"Unsupported client type: {type(database.client)}")
            self._clients[db_id] = client

        return client

    async def close(self) -> None:
        """Close all health check clients."""
        close_tasks = [
            asyncio.create_task(client.aclose()) for client in self._clients.values()
        ]

        if close_tasks:
            await asyncio.gather(*close_tasks, return_exceptions=True)

        self._clients.clear()

    @abstractmethod
    async def _execute(self, health_check: HealthCheck, database) -> bool:
        """

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Use one of the supported types directly — set `MultiDbConfig.client_class` to `Redis` or `RedisCluster` (sync or async variants as appropriate).
  2. If subclassing, ensure your subclass still passes `isinstance(client, (AsyncRedis, SyncRedis, AsyncRedisCluster, SyncRedisCluster))`.
  3. In tests, provide a real (or testcontainer-backed) Redis client rather than an unrelated mock as the database client.

Example fix

# before
class MyRedis(redis.asyncio.Redis):
    ...  # but constructed in a way isinstance fails, or a non-Redis wrapper
client = MultiDBClient(MultiDbConfig(
    databases_config=[DatabaseConfig(client_kwargs={})],
    client_class=MyRedis,  # if MyRedis is not a Redis subclass
))

# after
client = MultiDBClient(MultiDbConfig(
    databases_config=[DatabaseConfig(from_url='redis://host:6379/0')],
    client_class=redis.asyncio.Redis,
))
Defensive patterns

Strategy: type-guard

Validate before calling

import redis.asyncio as aioredis
from redis.asyncio import RedisCluster as AsyncRedisCluster
from redis.client import Redis as SyncRedis
from redis.cluster import RedisCluster as SyncRedisCluster

def client_is_supported(database) -> bool:
    return isinstance(database.client, (aioredis.Redis, SyncRedis, AsyncRedisCluster, SyncRedisCluster))

Type guard

import redis.asyncio as aioredis
from redis.asyncio import RedisCluster as AsyncRedisCluster
from redis.client import Redis as SyncRedis
from redis.cluster import RedisCluster as SyncRedisCluster

def is_supported_client(database) -> bool:
    return isinstance(database.client, (aioredis.Redis, SyncRedis, AsyncRedisCluster, SyncRedisCluster))

Try / catch

try:
    await client.initialize()
except TypeError as e:
    if 'Unsupported client type' in str(e):
        # switch client_class to Redis/RedisCluster in MultiDbConfig
        ...
    raise

Prevention

When it happens

Trigger: Passing a `DatabaseConfig` whose underlying client is a custom subclass or a non-Redis object (e.g. a test double/mock, a wrapped client, or a Sentinel-managed client) and triggering `get_client()` during a health check.

Common situations: Subclassing `redis.asyncio.Redis` in a way that breaks `isinstance`; injecting a mock client in tests; using a third-party Redis wrapper as the `client_class` in MultiDbConfig.

Related errors


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