Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Redis By James Joyner IV · · 8 min read Last reviewed Jul 2026

Redis Error Guide: 'ERR DISCARD without MULTI' — Fix Transaction Cleanup Logic

Quick answer

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
Free toolkit

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

  • DISCARD fails in error-handling / finally blocks, often after the “real” work already succeeded.
  • Shows up right after a successful EXEC, or after a MULTI that 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 MULTI is 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 MULTI and MULTI calls can not be nested; a codebase that hits one often hits the others.
  • Don’t swallow the original exception behind a noisy DISCARD error in your finally block.

Paste the failing command into the free incident assistant, and browse more Redis guides.

Free download · 368-page PDF

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?

Free download · 368-page PDF

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.