redis/jedis · error · JedisException
Active database has changed since transaction started
Error message
Active database has changed since transaction started
What it means
MultiDbTransaction buffers commands locally. Pre-MULTI commands (e.g. WATCH) execute immediately against the database that was active when the transaction started (initialDatabase). appendCommand throws JedisException("Active database has changed since transaction started") when a follow-up command arrives while the active database differs from initialDatabase, because commands would hit a different Redis instance and break transaction semantics.
Solutions
- Complete (exec/discard) the transaction before triggering or waiting for failover
- Catch JedisException and rebuild the transaction on the new active database (retry the whole WATCH/MULTI/EXEC cycle)
- Check the active database (connectionSupplier.isActiveDatabase) before starting a transaction and keep transactions short
Example fix
// before
Transaction t = client.transaction();
t.watch("k");
failover(); // active db changed
t.set("k", "v"); // throws
// after
Transaction t = client.transaction();
try {
t.watch("k");
t.set("k", "v");
t.exec();
} catch (JedisException e) {
t.close();
t = client.transaction(); // retry on new active db
} Defensive patterns
Strategy: retry
Validate before calling
if (!connectionSupplier.isActiveDatabase(initialDatabase)) { /* rebuild transaction on new active db */ } Try / catch
try { resp = t.set(key, value); } catch (JedisException e) { t.close(); t = client.transaction(); /* retry full WATCH/MULTI/EXEC */ } Prevention
- Keep transactions short so failover is unlikely mid-transaction
- Avoid triggering failover while transactions are open
- Retry the entire transaction (WATCH incl.) on active-database change
When it happens
Trigger: Calling any command (via status()/response() buffering path) on a MultiDbTransaction after a failover switched the active database, while the transaction had recorded an initialDatabase and is not yet in buffered MULTI mode.
Common situations: MultiDb failover triggered mid-transaction by health check failure; long-lived transaction objects spanning a database switch; tests or apps that call failoverToAnotherDatabase while a transaction is open.
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
- failed to connect. Please check configuration and try again.
- Endpoint does not exist.
- It is not allowed to create Transaction from this
- DatabaseClientConfigs are required for…
- DatabaseClientConfigs must not contain null elements
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/46dc3f27239f5de6.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/mcf/MultiDbTransaction.java:117
@Override
public final String unwatch() {
Response<String> response = appendCommand(
new CommandObject<>(new CommandArguments(UNWATCH), BuilderFactory.STRING));
inWatch = false;
// when inside MULTI, the command has only been buffered; its reply will be delivered by exec()
return inMulti ? null : response.get();
}
@Override
protected final <T> Response<T> appendCommand(CommandObject<T> commandObject) {
if (inMulti) {
CommandArguments args = commandObject.getArguments();
Response<T> response = new Response<>(commandObject.getBuilder());
commands.add(KeyValue.of(args, response));
return response;
}
if (initialDatabase != null && !connectionSupplier.isActiveDatabase(initialDatabase)) {
throw new JedisException("Active database has changed since transaction started");
}
try {
return Response.of(acquireConnection().executeCommand(commandObject));
} catch (JedisDataException e) {
return Response.error(e);
}
}
@Override
public void close() {
try {
if (inMulti) {
discard();
} else if (inWatch) {
unwatch();
}
} finally {
releaseConnection(false);View on GitHub (pinned to 6dac31d4c2)