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
Raised by PipelineStrategy.unlink() in redis/cluster.py:4576 when more than one key is passed. UNLINK is the non-blocking DEL; the same cross-slot constraint applies in a non-transactional cluster pipeline, so the method restricts to a single key.
Solutions
- Unlink keys one at a time: for k in keys: pipe.unlink(k).
- Use a transactional pipeline if keys share a hash tag and atomicity is needed.
- Call rc.unlink(*keys) outside the pipeline for standalone-style routing.
Example fix
// before
with rc.pipeline() as pipe:
pipe.unlink('k1', 'k2', 'k3')
pipe.execute()
// after
with rc.pipeline() as pipe:
for k in ['k1', 'k2', 'k3']:
pipe.unlink(k)
pipe.execute() Defensive patterns
Strategy: validation
Validate before calling
keys = ['k1', 'k2', 'k3']
with rc.pipeline() as pipe:
for k in keys:
pipe.unlink(k)
pipe.execute() Type guard
def is_single_key(names) -> bool:
return len(names) == 1 Try / catch
from redis.exceptions import RedisClusterException
try:
pipe.unlink(*keys)
except RedisClusterException:
for k in keys:
pipe.unlink(k) Prevention
- Never multi-key unlink in a non-transactional cluster pipeline.
- Loop single-key unlinks, or use rc.unlink(*keys) outside the pipeline.
When it happens
Trigger: Calling pipe.unlink('k1', 'k2', 'k3') (multiple keys) on a non-transactional ClusterPipeline, particularly when keys hash to different slots.
Common situations: Bulk-cleanup code using UNLINK for lazy deletion, ported from standalone to cluster; passing a variable-length key list.
Related errors
- unlinking multiple keys is not implemented in pipeline…
- All keys involved in a cluster transaction must map to the…
- At least a command with a key is needed to identify a node
- Cannot identify slot number for command
- Cannot watch or send commands on different slots
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/31c9cc5e63e79836.
Report an issue: GitHub.
Appendix: source
Thrown at redis/cluster.py:4576
"method watch() is not supported outside of transactional context"
)
def unwatch(self, *names):
raise RedisClusterException(
"method unwatch() is not supported outside of transactional context"
)
def delete(self, *names):
if len(names) != 1:
raise RedisClusterException(
"deleting multiple keys is not implemented in pipeline command"
)
return self.execute_command("DEL", names[0])
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)