redis/redis-py · error · TypeError

Async Redis client does not support class inclusion

Error message

Async Redis client does not support class inclusion

What it means

Raised by AsyncBasicKeyCommands.__contains__ (a TypeError) when you use 'key in async_client' on an async Redis client. The sync client would map this to EXISTS, but __contains__ cannot return an awaitable, so the async client forbids it to avoid returning a coroutine that would always be truthy.

Solutions

  1. Replace "key in client" with "bool(await client.exists(key))".
  2. For multiple keys, use the returned count from exists().

Example fix

# before
if 'mykey' in client:
    ...

# after
if await client.exists('mykey'):
    ...
Defensive patterns

Strategy: validation

Validate before calling

# Never use 'in' on an async client; call exists explicitly.
exists = bool(await client.exists(key))  # instead of 'key in client'

Type guard

import redis

def is_async_client(c) -> bool:
    return isinstance(c, (redis.asyncio.Redis, redis.asyncio.RedisCluster))

Try / catch

try:
    _ = key in client
except TypeError as e:
    if 'class inclusion' in str(e):
        result = bool(await client.exists(key))
    else:
        raise

Prevention

When it happens

Trigger: Writing "if 'mykey' in client:" or "'mykey' in client" where client is a redis.asyncio.Redis instance.

Common situations: Porting sync code that checks key existence via 'in'. The 'in' operator on an awaitable would silently always evaluate to True (coroutines are truthy), which is why the library blocks it.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:4812

        """
        pieces: list[str | int] = [key1, key2]
        if len:
            pieces.append("LEN")
        if idx:
            pieces.append("IDX")
        if minmatchlen is not None and minmatchlen != 0:
            pieces.extend(["MINMATCHLEN", minmatchlen])
        if withmatchlen:
            pieces.append("WITHMATCHLEN")
        return self.execute_command("LCS", *pieces, keys=[key1, key2])


class AsyncBasicKeyCommands(BasicKeyCommands):
    def __delitem__(self, name: KeyT):
        raise TypeError("Async Redis client does not support class deletion")

    def __contains__(self, name: KeyT):
        raise TypeError("Async Redis client does not support class inclusion")

    def __getitem__(self, name: KeyT):
        raise TypeError("Async Redis client does not support class retrieval")

    def __setitem__(self, name: KeyT, value: EncodableT):
        raise TypeError("Async Redis client does not support class assignment")

    async def watch(self, *names: KeyT) -> None:
        return super().watch(*names)

    async def unwatch(self) -> None:
        return super().unwatch()


class ListCommands(CommandsProtocol):
    """
    Redis commands for List data type.
    see: https://redis.io/topics/data-types#lists

View on GitHub (pinned to 6a6b581b48)