tursodatabase/turso · warning

Failed to rollback transaction during close

Error message

Failed to rollback transaction during close

What it means

TursoConnection.close() (bindings/java .../TursoConnection.java:83) checks isClosed(), then under transactionLock rolls back any open transaction via execute_internal("ROLLBACK") before closing. If that ROLLBACK throws, the SQLException is caught and logged at WARN level as "Failed to rollback transaction during close" through tech.turso.utils.Logger; inTransaction is cleared and the native connection is still closed via _close(connectionPtr). So this is a logged symptom, not a thrown error: the pending transaction could not be unwound, usually because the underlying engine already failed (I/O error, missing/unwritable file, poisoned connection).

Source

Thrown at bindings/java/src/main/java/tech/turso/core/TursoConnection.java:83

  }

  public String getUrl() {
    return url;
  }

  public void close() throws SQLException {
    if (isClosed()) {
      return;
    }

    // Roll back any pending transaction before closing
    synchronized (transactionLock) {
      if (inTransaction) {
        try {
          executeInternal("ROLLBACK");
        } catch (SQLException e) {
          // Log but don't throw - we're closing anyway
          logger.warn("Failed to rollback transaction during close", e);
        } finally {
          inTransaction = false;
        }
      }
    }

    this._close(this.connectionPtr);
    this.closed = true;
  }

  private native void _close(long connectionPtr);

  private native boolean _getAutoCommit(long connectionPtr);

  public boolean isClosed() throws SQLException {
    return closed;
  }

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Always commit or rollback explicitly in application finally blocks; treat close() as a last resort, not the transaction unwind.
  2. Read the WARN log's attached exception - it carries the SQLException with the underlying cause (I/O error, lock, disk full); fix that root cause.
  3. Check whether the connection was already poisoned by an earlier error; if so, the rollback failure is a symptom and the earlier failure is the real bug.
  4. Upgrade the Java bindings; close-time rollback handling may be improved in newer releases.

Example fix

// before: relying on close() to unwind the transaction
try (Connection conn = driver.connect(url, props)) {
    conn.setAutoCommit(false);
    stmt.executeUpdate("UPDATE t SET x = 1");
} // close() attempts rollback, logs WARN on failure

// after: explicit rollback before close
Connection conn = driver.connect(url, props);
try {
    conn.setAutoCommit(false);
    stmt.executeUpdate("UPDATE t SET x = 1");
    conn.commit();
} catch (SQLException e) {
    try { conn.rollback(); } catch (SQLException re) { log.warn("rollback failed", re); }
    throw e;
} finally {
    conn.close();
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before closing: end the transaction explicitly so close() never needs to roll back.
if (!conn.isClosed() && !conn.getAutoCommit()) {
    conn.rollback(); // or commit() - decide deliberately, not at close time
}
conn.close();

Try / catch

finally {
    if (conn != null) {
        try {
            if (!conn.getAutoCommit()) conn.rollback();
        } catch (SQLException rollbackEx) {
            log.warn("rollback before close failed", rollbackEx); // capture the cause here
        } finally {
            try { conn.close(); } catch (SQLException closeEx) {
                log.warn("close failed", closeEx);
            }
        }
    }
}

Prevention

When it happens

Trigger: Calling close() while a transaction is open (autoCommit=false with uncommitted writes) and the ROLLBACK itself fails - disk full, WAL on removed network storage, a prior fatal native error that already invalidated the connection, or close racing concurrent statement execution on the same connection.

Common situations: Application or connection-pool shutdown with uncommitted transactions, database files on removable/network mounts, disk exhaustion, code that swallows an earlier SQLException and closes anyway.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/e2d1bd3214e763d8. Report an issue: GitHub.