How to fix ERR DISCARD without MULTI in Redis

RedisBEGINNERMEDIUMUpdated Dec 29, 2025· 99 views

This error occurs when you call DISCARD without first starting a transaction with MULTI. DISCARD is only valid within an active transaction context, and calling it outside that context causes Redis to return this error.

Quick fix

Fixes ERR DISCARD without MULTI

MULTI -> Queue commands -> (EXEC or DISCARD)
  1. Verify transaction state before calling DISCARD
  2. Check for concurrent connection usage
  3. Implement proper exception handling in transactions
  4. Use client libraries with transaction abstractions
redis — error
MULTI -> Queue commands -> (EXEC or DISCARD)
ERR DISCARD without MULTI

What this error means

In Redis, transactions are initiated with the MULTI command, which puts the connection into transaction mode. During this mode, subsequent commands are queued rather than executed immediately. The DISCARD command is used to abort the transaction and discard all queued commands, restoring the connection to normal state. When you call DISCARD without a corresponding active MULTI command, Redis returns this error because there is no transaction context to abort. This typically happens due to transaction state mismanagement, connection sharing issues, or race conditions in concurrent environments.

Typical symptoms

  • Redis client returns "(error) ERR DISCARD without MULTI" response
  • Transaction handling fails unexpectedly in production
  • Errors appear intermittently in concurrent/multi-threaded applications
  • Connection state becomes inconsistent after transaction operations

Common causes

  1. Calling DISCARD in normal mode instead of transaction mode
  2. Transaction already completed or rolled back before DISCARD is called
  3. Concurrent requests on shared Redis connections causing command interleaving
  4. Exception thrown during MULTI causing transaction to auto-commit, then DISCARD called
  5. Connection timeout or failure leaving transaction state undefined
  6. Improper error handling causing DISCARD to execute when transaction is not active

How to fix "ERR DISCARD without MULTI"

1Verify transaction state before calling DISCARD

Always ensure MULTI has been called on the connection before attempting DISCARD. The proper transaction flow is:

bash
MULTI -> Queue commands -> (EXEC or DISCARD)

Never call DISCARD on a connection that is not in transaction mode.

2Check for concurrent connection usage

If using connection pooling or sharing connections across multiple threads/requests, ensure proper synchronization. Each logical transaction should use a dedicated connection:

python
# Bad: shared connection
redis_conn = get_shared_connection()
redis_conn.multi()
# ... another thread uses redis_conn here ...
redis_conn.discard()  # Error: DISCARD without MULTI

# Good: connection per transaction
with redis.pipeline(transaction=True) as pipe:
    pipe.multi()
    pipe.set('key', 'value')
    pipe.execute()
3Implement proper exception handling in transactions

Wrap transaction logic in try-catch blocks to prevent DISCARD from executing if an exception occurs:

python
try:
    redis_conn.multi()
    redis_conn.set('key1', 'value1')
    redis_conn.incr('counter')
    redis_conn.execute()
except Exception as e:
    # DISCARD only if transaction is still active
    try:
        redis_conn.discard()
    except ResponseError:
        # Transaction already aborted, connection is clean
        pass
    raise
4Use client libraries with transaction abstractions

Modern Redis client libraries provide abstractions that handle MULTI/EXEC/DISCARD automatically:

python
# Using redis-py pipeline (manages transaction state)
with redis_client.pipeline(transaction=True) as pipe:
    pipe.set('key1', 'value1')
    pipe.incr('counter')
    results = pipe.execute()

# Using Jedis in Java
try (Jedis jedis = jedisPool.getResource()) {
    Pipeline pipeline = jedis.pipelined();
    pipeline.watch("key");
    pipeline.multi();
    pipeline.set("key", "value");
    List<Object> results = pipeline.exec();  // Handles DISCARD on watch failure
}
5Monitor connection state in production

Implement logging and monitoring to detect transaction state issues:

python
import logging
import redis

logger = logging.getLogger(__name__)

class MonitoredRedis:
    def __init__(self, client):
        self.client = client
        self.in_transaction = False
    
    def multi(self):
        logger.debug("Starting transaction")
        self.in_transaction = True
        return self.client.multi()
    
    def discard(self):
        if not self.in_transaction:
            logger.error("DISCARD called without MULTI")
            raise RuntimeError("DISCARD without MULTI")
        self.in_transaction = False
        return self.client.discard()

Advanced notes

In multi-threaded environments, consider using Lua scripts instead of MULTI/EXEC. Lua scripts are atomic and eliminate transaction state management complexity: redis.eval("redis.call('set', KEYS[1], ARGV[1]); return redis.call('incr', KEYS[2])", 2, 'key1', 'counter', 'value1'). For distributed systems with connection pooling, prefer client library transaction wrappers (pipelines) that automatically manage transaction context. Note that Redis transactions do not support rollbacks—once EXEC completes, all commands have been applied. This is by design for performance reasons.

Frequently asked questions

What does "ERR DISCARD without MULTI" mean?
In Redis, transactions are initiated with the MULTI command, which puts the connection into transaction mode. During this mode, subsequent commands are queued rather than executed immediately. The DISCARD command is used to abort the transaction and discard all queued commands, restoring the connection to normal state.
How do I fix "ERR DISCARD without MULTI"?
This error occurs when you call DISCARD without first starting a transaction with MULTI. DISCARD is only valid within an active transaction context, and calling it outside that context causes Redis to return this error.
What causes "ERR DISCARD without MULTI"?
Calling DISCARD in normal mode instead of transaction mode Transaction already completed or rolled back before DISCARD is called Concurrent requests on shared Redis connections causing command interleaving
Is the "ERR DISCARD without MULTI" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading