pentaho/pentaho-kettle · warning · KettleDatabaseException
TransMeta.Log.UserCancelledTransSave
TransMeta.Log.UserCancelledTransSave
Error message
User canceled saving of transformation.
What it means
While saving notes during saveTransformation(), the delegate checks the progress monitor before each note and throws a KettleDatabaseException 'User canceled saving of transformation.' when monitor.isCanceled() is true. This is a deliberate cancellation signal, not a database failure, despite the exception type.
Solutions
- This is expected user behavior — catch KettleDatabaseException whose message is the cancellation key and treat it as a normal cancel, not an error.
- Ensure the transformation remains loadable: a canceled save can leave partial rows; delete or re-save the transformation afterward.
- If cancels are unintentional, don't pass an already-canceled monitor, or pass null when no progress reporting is needed.
- Inform the user the save was not completed before they close the transformation.
Example fix
// before
repository.save(transMeta, "c", monitor, false);
// after
try {
repository.save(transMeta, "c", monitor, false);
} catch (KettleDatabaseException e) {
if (monitor != null && monitor.isCanceled()) {
log.logBasic("Save cancelled by user");
return; // treat as cancel, not failure
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (monitor != null && monitor.isCanceled()) return; // don't start a doomed save
Try / catch
try {
repository.save(transMeta, comment, monitor, false);
} catch (KettleDatabaseException e) {
if (monitor != null && monitor.isCanceled()) return; // user cancel
throw e;
} Prevention
- Never pass a pre-canceled monitor
- Treat cancellation messages as normal flow, not DB failures
- Warn users that canceling mid-save leaves partial rows
When it happens
Trigger: repository.save(transMeta, comment, monitor, overwrite) with a ProgressMonitor that the user pressed Cancel on while the notes loop (transMeta.nrNotes()) is iterating.
Common situations: User cancels the save progress dialog of a big transformation; UI timeout/cancel button triggers monitor cancellation mid-save; automated callers pass a monitor that is canceled from the start.
Related errors
- Could not retrieve version history of object with path
- DELETE_JOB : repository is read-only
- " + element.getName() + " has a null id
- ERROR_0002_Cannot_Load_Job_From_Repository
- FuzzyMatchMeta.Exception.UnexpecteErrorReadingStepInfoFromRe…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/6344cabfcef4caa3.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryTransDelegate.java:221
}
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "TransMeta.Log.DeletingOldVersionTransformation" ) );
}
repository.deleteTransformation( transMeta.getObjectId() );
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "TransMeta.Log.OldVersionOfTransformationRemoved" ) );
}
}
if ( monitor != null ) {
monitor.worked( 1 );
}
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "TransMeta.Log.SavingNotes" ) );
}
for ( int i = 0; i < transMeta.nrNotes(); i++ ) {
if ( monitor != null && monitor.isCanceled() ) {
throw new KettleDatabaseException( BaseMessages.getString( PKG, "TransMeta.Log.UserCancelledTransSave" ) );
}
// if (monitor != null) monitor.subTask(BaseMessages.getString(PKG, "TransMeta.Monitor.SavingNoteTask.Title") +
// (i + 1) + "/" + transMeta.nrNotes());
NotePadMeta ni = transMeta.getNote( i );
repository.saveNotePadMeta( ni, transMeta.getObjectId() );
if ( ni.getObjectId() != null ) {
repository.insertTransNote( transMeta.getObjectId(), ni.getObjectId() );
}
if ( monitor != null ) {
monitor.worked( 1 );
}
}
if ( log.isDebug() ) {
log.logDebug( BaseMessages.getString( PKG, "TransMeta.Log.SavingDatabaseConnections" ) );
}
for ( DatabaseMeta databaseMeta : transMeta.getDatabaseManagementInterface().getAll() ) {View on GitHub (pinned to f3058517a1)