pentaho/pentaho-kettle · error · KettleException

JobEntryDeleteFiles.UnableToSaveToRepo

Error message

JobEntryDeleteFiles.UnableToSaveToRepo

What it means

Kettle wraps a KettleDatabaseException thrown while persisting the 'Delete Files' job entry's file arguments (name/filemask pairs) into the repository. The message includes the job id to identify which job's metadata failed to save. It is thrown from saveRep() when rep.saveJobEntryAttribute() fails for any row.

Solutions

  1. Check the repository database is reachable and the cause (dbe) chained in the exception logs the real SQL error
  2. Run the Kettle repository upgrade scripts so r_jobentry_attribute exists and matches your Pentaho version
  3. Verify the DB user has INSERT/UPDATE/DELETE rights on the repository tables
  4. Retry the save after restoring connectivity; reduce attribute length if a column-size error appears

Example fix

// before
jobEntry.saveRep(rep, metaStore, idJob); // throws KettleException on DB failure
// after
try {
  jobEntry.saveRep(rep, metaStore, idJob);
} catch (KettleException e) {
  logError("Could not save DeleteFiles entry for job " + idJob, e); // inspect chained KettleDatabaseException
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before save
if (!rep.isConnected() && rep instanceof KettleDatabaseRepository) {
  throw new IllegalStateException("Repository not connected");
}
// ensure arguments/filemasks are non-null and paired
if (jobEntry.getArguments() == null || jobEntry.getFilemasks() == null) {
  throw new IllegalStateException("arguments/filemasks must be initialized before save");
}

Type guard

boolean repositoryReady(Repository rep) {
  return rep != null && !(rep instanceof KettleDatabaseRepository)
    || ((KettleDatabaseRepository) rep).isConnected();
}

Try / catch

try {
  jobEntry.saveRep(rep, metaStore, idJob);
} catch (KettleException e) {
  Throwable cause = e.getCause();
  if (cause instanceof KettleDatabaseException) {
    // log SQL detail, alert, optionally queue for retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling saveRep() (directly or via JobMeta.save / repository export) when the underlying database insert/update of the 'name' or 'filemask' attributes fails, e.g. the r_jobentry_attribute table is missing, locked, or the connection dropped mid-save.

Common situations: Repository database down or network dropped during save; missing Kettle schema tables (no r_jobentry_attribute); DB permissions revoked; attribute value too long for column; repository connection configured wrong in ~/.kettle/repositories.xml.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/19cbe6375fbc9a4b. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/deletefiles/JobEntryDeleteFiles.java:190

      throw new KettleException( BaseMessages.getString( PKG, "JobEntryDeleteFiles.UnableToLoadFromRepo", String
        .valueOf( id_jobentry ) ), dbe );
    }
  }

  public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_job ) throws KettleException {
    try {
      rep.saveJobEntryAttribute( id_job, getObjectId(), "arg_from_previous", argFromPrevious );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "include_subfolders", includeSubfolders );

      // save the arguments...
      if ( arguments != null ) {
        for ( int i = 0; i < arguments.length; i++ ) {
          rep.saveJobEntryAttribute( id_job, getObjectId(), i, "name", arguments[i] );
          rep.saveJobEntryAttribute( id_job, getObjectId(), i, "filemask", filemasks[i] );
        }
      }
    } catch ( KettleDatabaseException dbe ) {
      throw new KettleException( BaseMessages.getString( PKG, "JobEntryDeleteFiles.UnableToSaveToRepo", String
        .valueOf( id_job ) ), dbe );
    }
  }

  public Result execute( Result result, int nr ) throws KettleException {
    List<RowMetaAndData> resultRows = result.getRows();

    int numberOfErrFiles = 0;
    result.setResult( false );
    result.setNrErrors( 1 );

    if ( argFromPrevious && log.isDetailed() ) {
      logDetailed( BaseMessages.getString( PKG, "JobEntryDeleteFiles.FoundPreviousRows", String
        .valueOf( ( resultRows != null ? resultRows.size() : 0 ) ) ) );
    }

    //Set Embedded NamedCluster MetaStore Provider Key so that it can be passed to VFS
    if ( parentJobMeta.getNamedClusterEmbedManager() != null ) {

View on GitHub (pinned to f3058517a1)