redis/jedis · error · IllegalStateException
DISCARD without MULTI
Error message
DISCARD without MULTI
What it means
discard() cancels a buffered transaction and requires that multi() was called (inMulti == true), matching Redis semantics. If MULTI was never entered, there is no transaction to discard and the method throws IllegalStateException("DISCARD without MULTI").
Solutions
- Only call discard() after multi() was invoked; use close() for unconditional cleanup
- Guard with an inMulti/state check or catch IllegalStateException
- Ensure single ownership of the transaction lifecycle so close() isn't called after an explicit discard()
Example fix
// before
Transaction t = client.transaction();
t.discard(); // throws
// after
Transaction t = client.transaction();
t.multi();
t.set("k", "v");
t.discard(); Defensive patterns
Strategy: try-catch
Validate before calling
if (t.isInMulti()) t.discard(); // otherwise just close()
Type guard
boolean canDiscard(MultiDbTransaction t) { return t.isInMulti(); } Try / catch
try { t.discard(); } catch (IllegalStateException e) { /* transaction was never in MULTI; safe to ignore or close */ } Prevention
- Use close() (which handles both cases) instead of raw discard() in cleanup code
- Guard discard() with the multi-state check
- Avoid calling both discard() and close() on the same instance
When it happens
Trigger: Calling discard() on a MultiDbTransaction before multi(), or after a prior discard()/exec() already cleared the state (close() also calls discard internally).
Common situations: Double cleanup in finally blocks (close() after explicit discard()); defensive discard() on a freshly created transaction; error-handling paths that discard unconditionally.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- WATCH inside MULTI is not allowed
- EXEC without MULTI
- HashImport ' ' has been discarded
- Cannot use Jedis when in Multi. Please use Transaction or…
- Cannot use Jedis when in Pipeline. Please use Pipeline or…
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/6bc5a7b07e8bc314.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/mcf/MultiDbTransaction.java:219
formatted.add(response.get());
} catch (JedisDataException e) {
formatted.add(e);
}
}
return formatted;
} finally {
inMulti = false;
inWatch = false;
commands.clear();
releaseConnection(serverInMultiMode);
}
}
@Override
public final String discard() {
if (!inMulti) {
throw new IllegalStateException("DISCARD without MULTI");
}
try {
// MULTI itself is only issued from exec(), so the server never started a transaction.
// Buffered commands only exist locally, so there is nothing to roll back server-side
// unless we have already acquired a connection for pre-MULTI traffic (e.g. WATCH).
if (inWatch) {
acquireConnection().sendCommand(UNWATCH);
return connection.getStatusCodeReply();
}
return OK_STR;
} finally {
inMulti = false;
inWatch = false;
commands.clear();
releaseConnection(false);
}
}View on GitHub (pinned to 6dac31d4c2)