mybatis/mybatis-3 · error · RuntimeSqlException

Could not set AutoCommit to {}. Cause: {}

Error message

Could not set AutoCommit to {}. Cause: {}

What it means

Before executing a script, ScriptRunner.setAutoCommit aligns the connection's autoCommit flag with the runner's setting; if connection.setAutoCommit(...) throws (driver/DB refuses, connection dead, mid-transaction change disallowed), it is wrapped as RuntimeSqlException with the target value and cause.

Source

Thrown at src/main/java/org/apache/ibatis/jdbc/ScriptRunner.java:183

  /**
   * @deprecated Since 3.5.4, this method is deprecated. Please close the {@link Connection} outside of this class.
   */
  @Deprecated
  public void closeConnection() {
    try {
      connection.close();
    } catch (Exception e) {
      // ignore
    }
  }

  private void setAutoCommit() {
    try {
      if (autoCommit != connection.getAutoCommit()) {
        connection.setAutoCommit(autoCommit);
      }
    } catch (Throwable t) {
      throw new RuntimeSqlException("Could not set AutoCommit to " + autoCommit + ". Cause: " + t, t);
    }
  }

  private void commitConnection() {
    try {
      if (!connection.getAutoCommit()) {
        connection.commit();
      }
    } catch (Throwable t) {
      throw new RuntimeSqlException("Could not commit transaction. Cause: " + t, t);
    }
  }

  private void rollbackConnection() {
    try {
      if (!connection.getAutoCommit()) {
        connection.rollback();
      }

View on GitHub (pinned to 008069adb1)

Solutions

  1. Pass a fresh, free connection not participating in a managed transaction to ScriptRunner.
  2. Match the runner's autoCommit to the connection's actual state: runner.setAutoCommit(connection.getAutoCommit()) so no switch is attempted.
  3. If a managed transaction is required, run script statements through the transactional DataSource honoring its autoCommit instead of toggling it.
  4. Check the cause for connection-closed errors and re-acquire a connection before retrying.

Example fix

// before
ScriptRunner runner = new ScriptRunner(managedTxConnection);
runner.setAutoCommit(false); // throws: cannot change autoCommit mid-transaction

// after
ScriptRunner runner = new ScriptRunner(freshConnection);
runner.setAutoCommit(false);
Defensive patterns

Strategy: validation

Validate before calling

// before running, confirm the connection can honor the target autoCommit mode
if (runner.isAutoCommit() != connection.getAutoCommit()) {
  try {
    boolean previous = connection.getAutoCommit();
    connection.setAutoCommit(runner.isAutoCommit());
    connection.setAutoCommit(previous); // restore
  } catch (SQLException e) {
    throw new IllegalStateException("Connection cannot switch autoCommit; pass a free connection to ScriptRunner", e);
  }
}

Try / catch

catch (RuntimeSqlException e) when e.getMessage() != null && e.getMessage().contains("Could not set AutoCommit") -> treat the connection as unusable for scripting: obtain a new, unmanaged connection and retry once; do not retry on the same connection.

Prevention

When it happens

Trigger: new ScriptRunner(connection) then runScript, where the connection cannot switch autoCommit: connection already closed, an active transaction that the driver refuses to alter (e.g. inside a managed transaction), or DB/driver states (e.g. SQL Server XACT_ABORT, connection pools with fixed autoCommit) that reject the change.

Common situations: Container-managed or @Transactional connections passed to ScriptRunner; pooled connections recycled mid-run; scripts run against a connection that a prior failure left in a broken state; MariaDB/MySQL drivers during XA.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/48dc47b082c0c6cf. Report an issue: GitHub.