pentaho/pentaho-kettle · error · InvocationTargetException
Error saving job
Error message
Error saving job
What it means
JobSaveProgressDialog wraps the repository save of a JobMeta inside an IRunnableWithProgress run on a ProgressMonitorDialog. If rep.save(jobMeta, ...) throws a KettleException, it is rethrown as an InvocationTargetException with the message 'Error saving job'. The dialog then surfaces the cause, so the real reason is always in the nested KettleException.
Solutions
- Inspect the InvocationTargetException's cause (KettleException) for the real repository error message.
- Verify the repository connection is alive (reconnect via rep.connect()) before retrying the save.
- Check that the target repository directory grants write permission to the logged-in user.
- Resolve name/version conflicts (rename the job or adjust the version comment) and retry.
Example fix
// before
rep.save( jobMeta, versionComment, new ProgressMonitorAdapter( monitor ) );
// after
if ( !rep.isConnected() ) {
rep.connect( username, password );
}
rep.save( jobMeta, versionComment == null ? "" : versionComment, new ProgressMonitorAdapter( monitor ) ); Defensive patterns
Strategy: try-catch
Validate before calling
if ( rep == null || !rep.isConnected() ) {
throw new IllegalStateException( "Repository not connected before saving job" );
}
if ( jobMeta == null || jobMeta.getName() == null || jobMeta.getName().isEmpty() ) {
throw new IllegalStateException( "Job must have a name before saving" );
} Try / catch
try {
new JobSaveProgressDialog( shell, rep, jobMeta, versionComment ).open();
} catch ( InvocationTargetException e ) {
Throwable cause = e.getCause();
logError( "Job save failed: " + cause.getMessage(), cause );
MessageBox mb = new MessageBox( shell, SWT.ICON_ERROR );
mb.setMessage( BaseMessages.getString( PKG, "JobLog.JobSaveFailed", cause.getMessage() ) );
mb.open();
} Prevention
- Check repository connectivity before opening the save dialog.
- Ensure the user has write permission on the target repository directory.
- Always log e.getCause() — the wrapper message hides the real KettleException.
- Handle version-comment conflicts by prompting the user for a new comment or name.
When it happens
Trigger: Calling the dialog's open() when the repository save fails: repository connection dropped, user lacks write permission in the target directory, duplicate job name/version conflicts, or versionComment handling rejected by the repository.
Common situations: Saving to a disconnected repository after a network hiccup; saving into a read-only repository or a directory without write access; repository commit failure (e.g. database down); concurrent modification of the same job by another user.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- ERROR_0003_Cannot_Save_Job_Entry
- Error loading job
- GetSequenceMeta.Exception.UnableToSaveStepInfo
- GroupByMeta.Exception.UnableToSaveStepInfoToRepository
- JobEntryWaitForSQL.UnableSaveRep
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/147f2fea308b674b.
Report an issue: GitHub.
Appendix: source
Thrown at ui/src/main/java/org/pentaho/di/ui/job/dialog/JobSaveProgressDialog.java:59
/**
* Creates a new dialog that will handle the wait while saving a job...
*/
public JobSaveProgressDialog( Shell shell, Repository rep, JobMeta jobInfo, String versionComment ) {
this.shell = shell;
this.rep = rep;
this.jobMeta = jobInfo;
this.versionComment = versionComment;
}
public boolean open() {
boolean retval = true;
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run( IProgressMonitor monitor ) throws InvocationTargetException, InterruptedException {
try {
rep.save( jobMeta, versionComment, new ProgressMonitorAdapter( monitor ) );
} catch ( KettleException e ) {
throw new InvocationTargetException( e, "Error saving job" );
}
}
};
try {
ProgressMonitorDialog pmd = new ProgressMonitorDialog( shell );
pmd.run( true, true, op );
} catch ( InvocationTargetException e ) {
new ErrorDialog( shell, "Error saving job", "An error occured saving the job!", e );
retval = false;
} catch ( InterruptedException e ) {
new ErrorDialog( shell, "Error saving job", "An error occured saving the job!", e );
retval = false;
}
return retval;
}
}View on GitHub (pinned to f3058517a1)