Redis Error Guide: 'ERR DISCARD without MULTI' — Fix Transaction Cleanup Logic
Fix ERR DISCARD without MULTI in Redis: diagnose DISCARD called with no open transaction, double cleanup after EXEC, and connection-pool state assumptions.
- #redis
- #troubleshooting
- #errors
- #transactions
Stuck on this Redis error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
Redis returns DISCARD without MULTI when DISCARD is issued on a connection that is not currently inside a transaction. DISCARD exists to abandon a queued MULTI block; if no MULTI is open, there is nothing to discard, so Redis rejects it.
The literal error clients receive:
(error) ERR DISCARD without MULTI
This is the mirror image of EXEC without MULTI. It usually means cleanup code ran DISCARD unconditionally — after the transaction was already closed by EXEC, or on an error path where MULTI never actually opened.
Symptoms
DISCARDfails in error-handling /finallyblocks, often after the “real” work already succeeded.- Shows up right after a successful
EXEC, or after aMULTIthat itself failed. - Harmless-looking but pollutes logs and can mask the original error.
redis-cli DISCARD
(error) ERR DISCARD without MULTI
Common Root Causes
1. Cleanup runs DISCARD after EXEC already closed the block
EXEC ends the transaction. A finally/except that then calls DISCARD finds no open MULTI.
2. MULTI never actually executed
An exception (or a connection error) prevented MULTI from reaching the server, but the cleanup path still calls DISCARD.
3. Unconditional DISCARD in shared cleanup code
A generic “reset the connection” helper calls DISCARD on every connection, whether or not it was in a transaction.
4. Pooled connection assumed to be mid-transaction
Code borrowed a connection expecting it to be in MULTI (it was not) and tried to discard.
How to diagnose
Step 1: Check whether a transaction is actually open
redis-cli CLIENT LIST | grep -E 'multi=[0-9]'
multi=-1 means the connection is not in a transaction, so DISCARD is invalid there.
Step 2: Trace the order of MULTI / EXEC / DISCARD
Confirm whether EXEC already ran before DISCARD. Logging each transaction verb with the connection id makes the double-close obvious.
Step 3: Reproduce the sequence
redis-cli MULTI # OK
redis-cli SET a 1 # QUEUED
redis-cli EXEC # closes the transaction
redis-cli DISCARD # ERR DISCARD without MULTI
Step 4: Watch the live stream briefly
redis-cli MONITOR
Look for a DISCARD with no preceding open MULTI. Keep MONITOR short; it adds server load.
Fixes
Only DISCARD when a transaction is open
Track transaction state in your code and call DISCARD conditionally:
in_multi = False
try:
r.execute_command("MULTI"); in_multi = True
r.execute_command("SET", "a", "1")
r.execute_command("EXEC"); in_multi = False
finally:
if in_multi:
r.execute_command("DISCARD")
Let the client library manage transactions
The pipeline helper opens and closes the block for you, so no manual DISCARD is needed:
with r.pipeline(transaction=True) as pipe:
pipe.set("a", 1)
pipe.execute()
Make cleanup idempotent
If a generic reset helper must run DISCARD, catch and ignore this specific error rather than letting it surface.
Close instead of reset when state is unknown
Dropping the connection (so the pool makes a fresh one) is often simpler than trying to discard uncertain state.
What to watch out for
DISCARD without MULTIis usually a symptom of messy transaction bookkeeping, not the real failure — check what happened just before it.- Redis 7 lets you clear per-transaction state by
RESET, which returns the connection to a clean baseline (also clearing MULTI, subscriptions, and auth) — handy in pool cleanup. - The complementary errors are
EXEC without MULTIandMULTI calls can not be nested; a codebase that hits one often hits the others. - Don’t swallow the original exception behind a noisy
DISCARDerror in yourfinallyblock.
Related
- Redis Error: ‘ERR MULTI calls can not be nested’
- Redis Error: ‘ERR EXEC without MULTI’
- Redis Error: ‘EXECABORT Transaction discarded because of previous errors’
Paste the failing command into the free incident assistant, and browse more Redis guides.
Fixed it? Get 500 Redis & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.