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

  1. Inspect the cause exception for the underlying SQL error
  2. Verify the repository user has write privileges and the DB is writable / has free space
  3. Ensure the job entry has been assigned to a job (valid ObjectId) before saving
  4. 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

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


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)