redis/redis-py · error · TypeError

Async Redis client does not support class assignment

Error message

Async Redis client does not support class assignment

What it means

Raised by AsyncBasicKeyCommands.__setitem__ (a TypeError) when you use 'async_client[key] = value'. The sync client maps this to SET, but __setitem__ cannot be async, so the async client disallows it to avoid silently fire-and-forgetting a coroutine that never executes.

Solutions

  1. Replace "client[key] = value" with "await client.set(key, value)".
  2. For bulk sets, use a pipeline with await on execute().

Example fix

# before
client['mykey'] = 'myvalue'

# after
await client.set('mykey', 'myvalue')
Defensive patterns

Strategy: validation

Validate before calling

# Never use client[key] = value on an async client; call set explicitly.
await client.set(key, value)  # instead of client[key] = value

Type guard

import redis

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

Try / catch

try:
    client[key] = value
except TypeError as e:
    if 'class assignment' in str(e):
        await client.set(key, value)
    else:
        raise

Prevention

When it happens

Trigger: Writing "client['mykey'] = 'myvalue'" where client is a redis.asyncio.Redis instance.

Common situations: Porting sync code that used dict-style assignment. The assignment would create a coroutine that is never awaited, so the SET never reaches Redis — hence the hard error.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:4818

        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
    """

    @overload
    def blpop(
        self: SyncClientProtocol, keys: KeysT, timeout: Number | None = 0
    ) -> BlockingListPopResponse: ...

View on GitHub (pinned to 6a6b581b48)