pentaho/pentaho-kettle · error · KettleException
Unable to save job entry of type 'create Folder' to the…
Error message
Unable to save job entry of type 'create Folder' to the repository for id_job=${id_job} What it means
Kettle wraps any KettleDatabaseException raised while persisting a 'create Folder' job entry's attributes (foldername, fail_of_folder_exists) to the repository in this KettleException via saveRep. The database cause is preserved so the actual write failure can be diagnosed. It indicates the job entry's metadata could not be saved.
Solutions
- Inspect the cause exception for the underlying SQL error
- Verify the repository user has write privileges and the DB is writable / has free space
- Ensure the job entry has been assigned to a job (valid ObjectId) before saving
- Retry the save after restoring repository connectivity
Example fix
// before
jobEntry.saveRep(rep, metaStore, idJob); // may throw 'Unable to save job entry...'
// after
try {
jobEntry.saveRep(rep, metaStore, idJob);
} catch (KettleException e) {
logError("Save failed: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()));
// surface to user before job is stored
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before saveRep
if (rep == null) throw new IllegalArgumentException("Repository required");
if (!rep.isReadOnly()) { /* proceed */ } else throw new IllegalStateException("Repository is read-only"); Type guard
boolean isSaveFailure(KettleException e) {
return e.getMessage() != null && e.getMessage().contains("Unable to save job entry");
} Try / catch
try {
jobEntry.saveRep(rep, metaStore, idJob);
} catch (KettleException e) {
Throwable cause = e.getCause();
log.error("JobEntryCreateFolder save failed for id_job=" + idJob, cause);
if (cause instanceof KettleDatabaseException) {
// check privileges/disk, fix ObjectId, retry save
}
throw e;
} Prevention
- Grant the repository user write privileges
- Monitor repository DB disk space and connection health
- Ensure job entries have valid ObjectIds before saving
- Wrap saves in transaction-safe retry logic
When it happens
Trigger: Calling JobEntryCreateFolder.saveRep when saveJobEntryAttribute fails — repository connection lost, read-only repository account, constraint violation on r_jobentry_attribute, or getObjectId() is null/invalid so the attribute insert fails.
Common situations: Repository user lacks INSERT/UPDATE privileges; repository DB disk full; saving a job entry whose ObjectId is null (never persisted before) against a repository implementation that requires it; transient DB outage during job save.
Related errors
- AddSequenceMeta.Exception.UnableToSaveStepInfo
- ColumnExistsMeta.Exception.UnableToSaveStepInfo
- ColumnExistsMeta.Exception.UnexpectedErrorReadingStepInfo
- CreditCardValidatorMeta.Exception.UnableToSaveStepInfo
- CubeInputMeta.Exception.UnableToSaveStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9fa9435da3165dac.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/createfolder/JobEntryCreateFolder.java:116
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
foldername = rep.getJobEntryAttributeString( id_jobentry, "foldername" );
failOfFolderExists = rep.getJobEntryAttributeBoolean( id_jobentry, "fail_of_folder_exists" );
} catch ( KettleException dbe ) {
throw new KettleException(
"Unable to load job entry of type 'create Folder' from the repository for id_jobentry=" + id_jobentry,
dbe );
}
}
public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_job ) throws KettleException {
try {
rep.saveJobEntryAttribute( id_job, getObjectId(), "foldername", foldername );
rep.saveJobEntryAttribute( id_job, getObjectId(), "fail_of_folder_exists", failOfFolderExists );
} catch ( KettleDatabaseException dbe ) {
throw new KettleException( "Unable to save job entry of type 'create Folder' to the repository for id_job="
+ id_job, dbe );
}
}
public void setFoldername( String foldername ) {
this.foldername = foldername;
}
public String getFoldername() {
return foldername;
}
public String getRealFoldername() {
return environmentSubstitute( getFoldername() );
}
public Result execute( Result previousResult, int nr ) {
Result result = previousResult;View on GitHub (pinned to f3058517a1)