{"record":{"id":"88d57509a982e40a","repo":"pentaho/pentaho-kettle","slug":"database-exception-unabletorollbacktosavepoint","errorCode":null,"errorMessage":"Database.Exception.UnableToRollbackToSavepoint","messagePattern":"Database\\.Exception\\.UnableToRollbackToSavepoint","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":5115,"sourceCode":"      throw new KettleDatabaseException( BaseMessages.getString(\n        PKG, \"Database.Exception.UnableToSetSavepointName\", savePointName ), e );\n    }\n  }\n\n  public void releaseSavepoint( Savepoint savepoint ) throws KettleDatabaseException {\n    try {\n      connection.releaseSavepoint( savepoint );\n    } catch ( SQLException e ) {\n      throw new KettleDatabaseException( BaseMessages.getString(\n        PKG, \"Database.Exception.UnableToReleaseSavepoint\" ), e );\n    }\n  }\n\n  public void rollback( Savepoint savepoint ) throws KettleDatabaseException {\n    try {\n      connection.rollback( savepoint );\n    } catch ( SQLException e ) {\n      throw new KettleDatabaseException( BaseMessages.getString(\n        PKG, \"Database.Exception.UnableToRollbackToSavepoint\" ), e );\n    }\n  }\n\n  public Object getParentObject() {\n    return parentLoggingObject;\n  }\n\n  /**\n   * Return primary key column names ...\n   *\n   * @param tablename\n   * @throws KettleDatabaseException\n   */\n  public String[] getPrimaryKeyColumnNames( String tablename ) throws KettleDatabaseException {\n    List<String> names = new ArrayList<>();\n    ResultSet allkeys = null;\n    try {","sourceCodeStart":5097,"sourceCodeEnd":5133,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L5097-L5133","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Create a fresh savepoint before each rollback-to-savepoint in retry loops","Confirm auto-commit is disabled for the whole transaction scope","If the connection is dead, do a full connection.rollback()/reconnect instead of partial rollback","Verify the Savepoint belongs to the current connection and transaction","Inspect the wrapped SQLException cause to distinguish connection loss from invalid savepoint"],"exampleFix":"// before\nSavepoint sp = database.setSavepoint();\n// retry loop reuses sp\ndatabase.rollback( sp ); // second time fails\n// after\nfor ( int attempt = 0; attempt < retries; attempt++ ) {\n  Savepoint sp = database.setSavepoint();\n  try {\n    doWork();\n    database.releaseSavepoint( sp );\n    break;\n  } catch ( KettleDatabaseException e ) {\n    database.rollback( sp );\n  }\n}","handlingStrategy":"try-catch","validationCode":"if ( database.getConnection().getAutoCommit() ) {\n  throw new IllegalStateException( \"Cannot rollback to savepoint with auto-commit on\" );\n}","typeGuard":null,"tryCatchPattern":"try {\n  database.rollback( savepoint );\n} catch ( KettleDatabaseException e ) {\n  log.error( \"Rollback to savepoint failed; performing full rollback\", e );\n  database.rollback(); // full transaction rollback fallback\n}","preventionTips":["Create a new savepoint before each retry attempt","Always keep auto-commit off in savepoint scopes","Fall back to full rollback on connection loss","Don't roll back to the same savepoint twice"],"tags":["jdbc","database","transaction","savepoint","rollback"],"backgroundTag":"database-query-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}