redis/jedis · error · IllegalStateException
Cannot use Jedis when in Multi. Please use Transaction or…
Error message
Cannot use Jedis when in Multi. Please use Transaction or reset jedis state.
What it means
Jedis's legacy single-connection client cannot run interactive commands while a MULTI transaction is open on it. checkIsInMultiOrPipeline throws IllegalStateException when the transaction field is non-null to prevent commands from being interleaved into the transaction unintentionally. The message directs you to use the Transaction object for commands or reset the Jedis state.
Solutions
- Execute the commands on the Transaction object instead of the Jedis instance (tx.ping() etc.)
- Commit (tx.exec()) or abort (tx.close()) the transaction before using jedis directly
- Discard/reset state: call jedis.resetState() to clear the multi flag
- Avoid sharing one Jedis instance between transactional and direct use; use JedisPool
Example fix
// before Transaction tx = jedis.multi(); jedis.flushDB(); // IllegalStateException: in Multi // after Transaction tx = jedis.multi(); tx.flushDB(); tx.exec(); // or, if the transaction is abandoned: jedis.resetState();
Defensive patterns
Strategy: validation
Validate before calling
if (jedis.isInMulti()) { // or track your own Transaction reference
throw new IllegalStateException("complete or reset the transaction first");
} Try / catch
try {
jedis.ping();
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Cannot use Jedis when in Multi")) {
jedis.resetState();
jedis.ping();
} else throw e;
} Prevention
- Never share a Jedis instance between transactional and direct command use
- Always commit/close Transactions in try-with-resources
- Call resetState() on error paths that abandon a transaction
- Route health-check pings through a separate pooled connection
When it happens
Trigger: Calling ping/select/swapDB/flushDB/flushAll/copy on a Jedis instance after jedis.multi() was called and before the Transaction was committed/aborted, e.g. doing health-check pings or a flushAll inside the transaction window.
Common situations: Shared Jedis instance used by monitoring code that pings while another thread has opened a transaction; forgetting to exec() or close() a Transaction so the Jedis stays in multi state; calling administrative commands (flushDB) inside transaction blocks for tests.
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
- HashImport ' ' has been discarded
- Cannot use Jedis when in Pipeline. Please use Pipeline or…
- setHostAndPort method has limited capability.
- It is not allowed to create Transaction from this
- MULTI command failed. Received response:
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/972d1314263b46fc.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/Jedis.java:431
@Override
protected void onAfterDiscard() {
resetState();
}
};
return transaction;
}
// Legacy
public Pipeline pipelined() {
pipeline = new Pipeline(this);
return pipeline;
}
// Legacy
protected void checkIsInMultiOrPipeline() {
// if (connection.isInMulti()) {
if (transaction != null) {
throw new IllegalStateException(
"Cannot use Jedis when in Multi. Please use Transaction or reset jedis state.");
} else if (pipeline != null && pipeline.hasPipelinedResponse()) {
throw new IllegalStateException(
"Cannot use Jedis when in Pipeline. Please use Pipeline or reset jedis state.");
}
}
public int getDB() {
return this.db;
}
/**
* @return <code>PONG</code>
*/
@Override
public String ping() {
checkIsInMultiOrPipeline();
connection.sendCommand(Command.PING);View on GitHub (pinned to 6dac31d4c2)