redis/redis-py · error · ConnectionError

Invalid Database

Error message

Invalid Database

What it means

Raised as ConnectionError during on_connect() when SELECT <db> returns a non-OK reply, meaning the server refused the database switch. The library only sends SELECT when self.db is truthy (non-zero). The most frequent cause is requesting a database index that does not exist on the server.

Solutions

  1. Use db=0 (the only supported index on Redis Cluster and most managed providers).
  2. Raise CONFIG SET databases N / the 'databases' directive in redis.conf and restart, if you genuinely need a higher index on standalone Redis.
  3. Remove the /<db> path component from the connection URL.
  4. If sharding by db is required, switch to multiple client instances each pointing at db 0 on different deployments.

Example fix

// before
r = redis.asyncio.from_url('redis://host:6379/20')
// after
r = redis.asyncio.from_url('redis://host:6379/0')
Defensive patterns

Strategy: validation

Validate before calling

def safe_db(db: int, max_databases: int = 16) -> int:
    if db < 0 or db >= max_databases:
        return 0
    return db

Type guard

from redis.exceptions import ConnectionError

def is_invalid_db(exc: BaseException) -> bool:
    return isinstance(exc, ConnectionError) and 'invalid database' in str(exc).lower()

Try / catch

from redis.exceptions import ConnectionError

try:
    await client.select(db)
except ConnectionError as e:
    if 'invalid database' in str(e).lower():
        await client.select(0)
    else:
        raise

Prevention

When it happens

Trigger: Constructing redis.asyncio.Redis(host=h, db=15) (or from_url('redis://host/15')) against a server configured with fewer than 16 databases, or a Redis Cluster target where SELECT to a non-zero db is not permitted.

Common situations: Default redis.conf databases=16 but user sets db=20; connecting to a managed Redis (cluster) that only allows db 0; leftover /N path in a copied URL pointing at an index the new provider does not have.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/fdb0f06f8c8f8a36. Report an issue: GitHub.

Appendix: source

Thrown at redis/asyncio/connection.py:1064

                self.driver_info.lib_version,
                check_health=check_health,
            )
            lib_version_sent = True

        # if a database is specified, switch to it. Also pipeline this
        if self.db:
            await self.send_command("SELECT", self.db, check_health=check_health)

        # read responses from pipeline
        for _ in range(sum([lib_name_sent, lib_version_sent])):
            try:
                await self.read_response()
            except ResponseError:
                pass

        if self.db:
            if str_if_bytes(await self.read_response()) != "OK":
                raise ConnectionError("Invalid Database")

    async def disconnect(
        self,
        nowait: bool = False,
        error: Optional[Exception] = None,
        failure_count: Optional[int] = None,
        health_check_failed: bool = False,
    ) -> None:
        """Disconnects from the Redis server"""
        # The server session is gone, so any HIMPORT fieldsets prepared on this
        # socket no longer exist; reset the tracking.
        self._reset_himport_state()
        # On Python 3.13+, asyncio.timeout() raises RuntimeError when called
        # outside a running Task (e.g. during GC finalization or event-loop
        # callbacks).  In that context we fall back to a synchronous close.
        # See https://github.com/redis/redis-py/issues/3856
        if asyncio.current_task() is None:
            self._parser.on_disconnect()

View on GitHub (pinned to 6a6b581b48)