tursodatabase/turso · error · SQLException
Cannot rollback in autocommit mode.
Error message
Cannot rollback in autocommit mode.
What it means
TursoConnection.rollback() refuses to run while autoCommit is true. With autocommit enabled each statement is committed on completion, so there is no open transaction to roll back and Turso throws instead of silently no-oping.
Source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoConnection.java:239
}
if (inTransaction) {
executeInternal("COMMIT");
inTransaction = false;
}
}
}
/**
* Rolls back the current transaction.
*
* @throws SQLException if in auto-commit mode, closed, or database error occurs.
*/
public void rollback() throws SQLException {
synchronized (transactionLock) {
checkOpen();
if (autoCommit) {
throw new SQLException("Cannot rollback in autocommit mode.");
}
if (inTransaction) {
executeInternal("ROLLBACK");
inTransaction = false;
}
}
}
/**
* Lazy transaction starter. Starts a transaction if one isn't active, auto-commit is disabled,
* and the statement isn't a control command.
*/
private void ensureTransactionStarted(String sql) throws SQLException {
if (autoCommit || inTransaction) return;
// Avoid recursive start for control statements
String trimmed = sql.trim().toUpperCase();View on GitHub (pinned to bad083fafb)
Solutions
- Call conn.setAutoCommit(false) before executing statements that may need rollback
- Guard the rollback: if (!conn.getAutoCommit()) { conn.rollback(); }
- Keep setAutoCommit(false), the try/catch/rollback, and commit in one helper so they cannot drift apart
Example fix
// before
try (Statement st = conn.createStatement()) {
st.executeUpdate("UPDATE t SET a = 1");
} catch (SQLException e) {
conn.rollback(); // throws: still in autocommit mode
}
// after
conn.setAutoCommit(false);
try (Statement st = conn.createStatement()) {
st.executeUpdate("UPDATE t SET a = 1");
conn.commit();
} catch (SQLException e) {
if (!conn.getAutoCommit()) conn.rollback();
} Defensive patterns
Strategy: validation
Validate before calling
if (conn.getAutoCommit()) {
// nothing to roll back — statements committed individually
} else {
conn.rollback();
} Try / catch
try {
conn.rollback();
} catch (SQLException e) {
if ("Cannot rollback in autocommit mode.".equals(e.getMessage())) {
// benign: no transaction was open
} else {
throw e;
}
} Prevention
- Write rollback handlers together with setAutoCommit(false), never as standalone catch-block boilerplate
- Guard every manual rollback with if (!conn.getAutoCommit())
- Return pooled connections with transactions explicitly committed or rolled back
When it happens
Trigger: Calling conn.rollback() on a connection where autoCommit is true — typically a catch block that rolls back without ever having disabled autocommit, or after a pool reset autoCommit to true.
Common situations: catch (Exception e) { conn.rollback(); } error handling written before setAutoCommit(false) was added; unit tests reusing one connection across cases; pool reset code re-enabling autocommit before the application's rollback runs.
Related errors
- Cannot commit in autocommit mode.
- Cannot change isolation level while transaction is active.
- Invalid transaction isolation level: ${level}
- SQLite only supports TYPE_FORWARD_ONLY cursors
- SQLite only supports CONCUR_READ_ONLY cursors
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/09492d933a094a26.
Report an issue: GitHub.