redis/redis-py · error · RedisClusterException
method discard() is not supported outside of transactional c
Error message
method discard() is not supported outside of transactional context
What it means
PipelineStrategy.discard() (redis/cluster.py:4529) always raises. DISCARD aborts a MULTI transaction; on a non-transactional pipeline (transaction=False) there is no transaction to abort, so the call is invalid. The strategy is selected at ClusterPipeline.__init__ (redis/cluster.py:3598).
Source
Thrown at redis/cluster.py:4530
elif request_policy == RequestPolicy.MULTI_SHARD:
nodes = policy_callback(*args, **kwargs)
elif request_policy == RequestPolicy.DEFAULT_KEYLESS:
nodes = policy_callback(args[0])
else:
nodes = policy_callback()
if args[0].lower() == "ft.aggregate":
self._aggregate_nodes = nodes
return nodes
def multi(self):
raise RedisClusterException(
"method multi() is not supported outside of transactional context"
)
def discard(self):
raise RedisClusterException(
"method discard() is not supported outside of transactional context"
)
def watch(self, *names):
raise RedisClusterException(
"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"
)View on GitHub (pinned to da03cdc7e8)
Solutions
- Guard discard() behind the transaction mode, or only call it on a transactional pipeline.
- For a non-transactional pipeline, clear queued commands with pipe.reset() instead of discard().
- Use rc.pipeline() (default transaction=True) if you need MULTI/DISCARD semantics.
Example fix
# before
pipe = rc.pipeline(transaction=False)
try:
pipe.discard() # raises
# after
pipe = rc.pipeline(transaction=False)
pipe.reset() # safe way to clear a non-transactional pipeline Defensive patterns
Strategy: validation
Validate before calling
def safe_discard(pipe):
# discard() is only valid on a transactional pipeline
if not getattr(pipe, '_execution_strategy', None).__class__.__name__ == 'TransactionStrategy':
pipe.reset() # non-transactional: just clear the queue
return
pipe.discard() Try / catch
from redis.exceptions import RedisClusterException
try:
pipe.discard()
except RedisClusterException:
pipe.reset() Prevention
- Use pipe.reset() to clear a non-transactional pipeline; reserve discard() for transactions.
- Guard cleanup blocks with the pipeline mode.
- Default to transaction=True if your cleanup code relies on DISCARD.
When it happens
Trigger: Calling pipe.discard() on a pipeline created with rc.pipeline(transaction=False).
Common situations: Reusable error-handling code that calls discard() to clean up a pipeline, run against a non-transactional pipeline. Cleanup/finally blocks that blindly discard. Migrating standalone patterns that use DISCARD defensively.
Related errors
- method multi() is not supported outside of transactional con
- At least a command with a key is needed to identify a node
- Cannot watch or send commands on different slots
- Cannot identify slot number for command: {args[0]},it cannot
- Cannot issue a WATCH after a MULTI
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/b6abe73090214557.json.
Report an issue: GitHub.