redis/redis-py · error · RedisClusterException

unlinking multiple keys is not implemented in pipeline…

Error message

unlinking multiple keys is not implemented in pipeline command

What it means

Thrown by the async ClusterPipeline non-atomic strategy's unlink() override (redis/asyncio/cluster.py:3052). In cluster mode a multi-key UNLINK cannot be routed to a single node because the keys may map to different hash slots, so only the single-key form is implemented inside a pipeline. Passing more than one key therefore fails fast rather than silently corrupting the pipeline. Use per-key calls or the non-pipeline client which fans out across slots.

Solutions

  1. Call unlink once per key: `for k in keys: await pipeline.unlink(k)`
  2. Use the regular cluster client `await client.unlink(*keys)` which fans out across slots, instead of the pipeline
  3. If all keys share a hash slot (hash tag), the non-atomic pipeline still requires single-key calls - loop over them

Example fix

// before
await pipeline.unlink('k1', 'k2', 'k3')
// after
for k in ('k1', 'k2', 'k3'):
    await pipeline.unlink(k)
Defensive patterns

Strategy: validation

Validate before calling

if len(keys) > 1:
    # cluster pipeline unlink supports only one key at a time
    for k in keys:
        await pipeline.unlink(k)
else:
    await pipeline.unlink(keys[0])

Try / catch

try:
    await pipeline.unlink(*keys)
except RedisClusterException as e:
    if 'unlinking multiple keys' in str(e):
        for k in keys:
            await pipeline.unlink(k)
    else:
        raise

Prevention

When it happens

Trigger: Calling `pipeline.unlink('k1', 'k2')` (or any variadic call with len(names) != 1) on an async redis.asyncio.RedisCluster pipeline using the default non-atomic execution strategy.

Common situations: Migrating a standalone Redis pipeline that batch-unlinks several keys into cluster mode; refactoring cleanup code that used `unlink(*keys_list)`.

Related errors


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

Appendix: source

Thrown at redis/asyncio/cluster.py:3054

    async def watch(self, *names):
        raise RedisClusterException(
            "method watch() is not supported outside of transactional context"
        )

    async def unwatch(self):
        raise RedisClusterException(
            "method unwatch() is not supported outside of transactional context"
        )

    async def discard(self):
        raise RedisClusterException(
            "method discard() is not supported outside of transactional context"
        )

    async def unlink(self, *names):
        if len(names) != 1:
            raise RedisClusterException(
                "unlinking multiple keys is not implemented in pipeline command"
            )

        return self.execute_command("UNLINK", names[0])


class TransactionStrategy(AbstractStrategy):
    NO_SLOTS_COMMANDS = {"UNWATCH"}
    IMMEDIATE_EXECUTE_COMMANDS = {"WATCH", "UNWATCH"}
    UNWATCH_COMMANDS = {"DISCARD", "EXEC", "UNWATCH"}
    SLOT_REDIRECT_ERRORS = (AskError, MovedError)
    CONNECTION_ERRORS = (
        ConnectionError,
        OSError,
        ClusterDownError,
        SlotNotCoveredError,
    )

View on GitHub (pinned to 6a6b581b48)