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

  1. Call conn.setAutoCommit(false) before executing statements that may need rollback
  2. Guard the rollback: if (!conn.getAutoCommit()) { conn.rollback(); }
  3. 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

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


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/09492d933a094a26. Report an issue: GitHub.