redis/jedis · error · IllegalStateException
WATCH inside MULTI is not allowed
Error message
WATCH inside MULTI is not allowed
What it means
MultiDbTransaction supports optimistic locking via WATCH only before a transaction block starts. Once multi() has been called (inMulti == true), Redis forbids WATCH, so this method throws IllegalStateException("WATCH inside MULTI is not allowed"). The transaction is still valid; only this call is rejected.
Solutions
- Call watch(...) before multi(...) on the transaction
- Use a fresh MultiDbTransaction instance for each MULTI block and WATCH on it first
- Restructure so keys are watched in a separate pre-transaction phase
Example fix
// before
Transaction t = ...;
t.multi();
t.watch("key");
// after
Transaction t = ...;
t.watch("key");
t.multi(); Defensive patterns
Strategy: validation
Validate before calling
if (transactionInMultiState(t)) throw new IllegalStateException("call watch() before multi()"); Type guard
boolean canWatch(MultiDbTransaction t) { return !t.isInMulti(); } Try / catch
try { t.watch(keys); } catch (IllegalStateException e) { /* re-create transaction and watch before multi */ } Prevention
- Always WATCH before MULTI in your transaction helper
- Wrap transaction setup in a single method enforcing the correct order
- Avoid reusing transaction objects across lifecycle states
When it happens
Trigger: Calling watch(String... keys) after multi() on the same MultiDbTransaction instance.
Common situations: Reused transaction objects where multi() was invoked earlier in the same flow; mixing Watch/Transaction API patterns; refactored code that moved watch() after multi().
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
- EXEC without MULTI
- DISCARD 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/59df668baeffa82f.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/mcf/MultiDbTransaction.java:82
public MultiDbTransaction(MultiDbConnectionProvider provider, boolean doMulti,
CommandObjects commandObjects) {
super(commandObjects);
this.connectionSupplier = new MultiDbConnectionSupplier(provider);
if (doMulti) {
multi();
}
}
@Override
public final void multi() {
inMulti = true;
}
@Override
public final String watch(String... keys) {
if (inMulti) {
throw new IllegalStateException("WATCH inside MULTI is not allowed");
}
String status = appendCommand(commandObjects.watch(keys)).get();
inWatch = true;
return status;
}
@Override
public final String watch(byte[]... keys) {
if (inMulti) {
throw new IllegalStateException("WATCH inside MULTI is not allowed");
}
String status = appendCommand(commandObjects.watch(keys)).get();
inWatch = true;
return status;
}
@Override
public final String unwatch() {View on GitHub (pinned to 6dac31d4c2)