tursodatabase/turso · error · SQLException
Cannot rollback in autocommit mode.
Error message
Cannot rollback in autocommit mode.
What it means
rollback() requires autoCommit to be false; calling it while still in autocommit mode throws. As with commit(), the driver only maintains transaction state after setAutoCommit(false) — a lazy BEGIN is issued on the first non-control statement, and rollback() then issues ROLLBACK. Rolling back outside a transaction is meaningless, hence the guard.
Solutions
- Call conn.setAutoCommit(false) before the unit of work begins
- Guard the rollback: `if (!conn.getAutoCommit()) conn.rollback();` in finally/catch
- Structure transactional code so rollback only runs on connections you explicitly prepared for transactions
Example fix
// before
try { runQueries(conn); } catch (SQLException e) { conn.rollback(); throw e; }
// after
conn.setAutoCommit(false);
try { runQueries(conn); conn.commit(); }
catch (SQLException e) { if (!conn.getAutoCommit()) conn.rollback(); throw e; } Defensive patterns
Strategy: validation
Validate before calling
// safe cleanup: rollback is a no-op unless a lazy transaction actually started
if (!conn.getAutoCommit()) {
conn.rollback();
} Try / catch
try {
runInTxn(conn);
} catch (SQLException e) {
if (!conn.getAutoCommit()) conn.rollback();
throw e;
} Prevention
- Guard every rollback in generic exception handlers with !conn.getAutoCommit()
- Take connections out of autocommit explicitly at the start of each transactional unit of work
- Ensure pool reset logic restores autoCommit before the application's finally block runs
When it happens
Trigger: Calling connection.rollback() in a catch block without a prior setAutoCommit(false); exception handlers that roll back unconditionally even for connections never taken out of autocommit; code after a pool reset autoCommit to true.
Common situations: Generic catch-and-rollback wrappers around code that sometimes runs in autocommit; connection pools restoring autoCommit=true before the application's finally block runs; partial refactors that removed setAutoCommit(false).
Related errors
- Cannot commit in autocommit mode.
- Cannot change isolation level while transaction is active.
- Failed to rollback transaction during close
- Invalid transaction isolation level
- BEGIN must start a transaction
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/09492d933a094a26.
Report an issue: GitHub.
Appendix: 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 244cde92a7)