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

  1. Call conn.setAutoCommit(false) before the unit of work begins
  2. Guard the rollback: `if (!conn.getAutoCommit()) conn.rollback();` in finally/catch
  3. 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

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


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)