pentaho/pentaho-kettle · error · KettleDatabaseException

Database.Exception.UnableToRollbackToSavepoint

Error message

Database.Exception.UnableToRollbackToSavepoint

What it means

Thrown by Database.rollback(Savepoint) (Database.java:5115) when connection.rollback(savepoint) fails with a SQLException. Means the transaction could not be partially rolled back to the given savepoint — often the savepoint was already consumed or the transaction is dead.

Solutions

  1. Create a fresh savepoint before each rollback-to-savepoint in retry loops
  2. Confirm auto-commit is disabled for the whole transaction scope
  3. If the connection is dead, do a full connection.rollback()/reconnect instead of partial rollback
  4. Verify the Savepoint belongs to the current connection and transaction
  5. Inspect the wrapped SQLException cause to distinguish connection loss from invalid savepoint

Example fix

// before
Savepoint sp = database.setSavepoint();
// retry loop reuses sp
database.rollback( sp ); // second time fails
// after
for ( int attempt = 0; attempt < retries; attempt++ ) {
  Savepoint sp = database.setSavepoint();
  try {
    doWork();
    database.releaseSavepoint( sp );
    break;
  } catch ( KettleDatabaseException e ) {
    database.rollback( sp );
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if ( database.getConnection().getAutoCommit() ) {
  throw new IllegalStateException( "Cannot rollback to savepoint with auto-commit on" );
}

Try / catch

try {
  database.rollback( savepoint );
} catch ( KettleDatabaseException e ) {
  log.error( "Rollback to savepoint failed; performing full rollback", e );
  database.rollback(); // full transaction rollback fallback
}

Prevention

When it happens

Trigger: Calling Database.rollback(savepoint) after commit, after a prior rollback to the same savepoint, on a connection with auto-commit on, or when the connection has been invalidated (network drop).

Common situations: Reusing a savepoint twice in retry logic (invalidated after first rollback); crash recovery paths rolling back on a dead connection; mixing commit and rollback-to-savepoint in the same flow.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/88d57509a982e40a. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:5115

      throw new KettleDatabaseException( BaseMessages.getString(
        PKG, "Database.Exception.UnableToSetSavepointName", savePointName ), e );
    }
  }

  public void releaseSavepoint( Savepoint savepoint ) throws KettleDatabaseException {
    try {
      connection.releaseSavepoint( savepoint );
    } catch ( SQLException e ) {
      throw new KettleDatabaseException( BaseMessages.getString(
        PKG, "Database.Exception.UnableToReleaseSavepoint" ), e );
    }
  }

  public void rollback( Savepoint savepoint ) throws KettleDatabaseException {
    try {
      connection.rollback( savepoint );
    } catch ( SQLException e ) {
      throw new KettleDatabaseException( BaseMessages.getString(
        PKG, "Database.Exception.UnableToRollbackToSavepoint" ), e );
    }
  }

  public Object getParentObject() {
    return parentLoggingObject;
  }

  /**
   * Return primary key column names ...
   *
   * @param tablename
   * @throws KettleDatabaseException
   */
  public String[] getPrimaryKeyColumnNames( String tablename ) throws KettleDatabaseException {
    List<String> names = new ArrayList<>();
    ResultSet allkeys = null;
    try {

View on GitHub (pinned to f3058517a1)