pentaho/pentaho-kettle · error · KettleException

JobCopyFiles.Error.Exception.UnableSaveRep

Error message

JobCopyFiles.Error.Exception.UnableSaveRep

What it means

JobEntryCopyFiles.saveRep throws this KettleException when persisting the job entry's configuration to the Pentaho repository fails. It wraps KettleDatabaseException raised while saving job entry attributes (source, destination, wildcard per row) and appends the object id.

Solutions

  1. Check repository DB connectivity and disk space / read-only state.
  2. Shorten attribute values (paths/wildcards) that exceed R_JOBENTRY_ATTRIBUTE column limits.
  3. Retry the save after resolving transient connection issues; commit/reopen the job.
  4. Inspect the chained KettleDatabaseException for the failing SQL statement.
Defensive patterns

Strategy: try-catch

Validate before calling

// before saving
for (String s : source) if (s != null && s.length() > 2000) throw new IllegalArgumentException("Source path too long for repository");
if (!rep.isConnected()) throw new IllegalStateException("Repository not connected before saveRep");

Try / catch

try {
  jobEntry.saveRep(rep, metaStore, id_job);
} catch (KettleException e) {
  logError("Repository save failed for id_job=" + id_job + ": " + e.getCause(), e);
  // notify user, keep in-memory job intact so the save can be retried
}

Prevention

When it happens

Trigger: Calling saveRep (job save to repository) when the repository connection fails, an attribute value violates a DB constraint (e.g. value too long for VALUE_STR column), or the job entry object id is invalid/not yet committed.

Common situations: Repository DB disk full or read-only; oversized wildcard/source path strings exceeding column length; network drop between Spoon and repository database; concurrent edits causing lock timeouts.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/copyfiles/JobEntryCopyFiles.java:320

      rep.saveJobEntryAttribute( id_job, getObjectId(), "arg_from_previous", arg_from_previous );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "overwrite_files", overwrite_files );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "include_subfolders", include_subfolders );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "remove_source_files", remove_source_files );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "add_result_filesname", add_result_filesname );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "destination_is_a_file", destination_is_a_file );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "create_destination_folder", create_destination_folder );

      // save the arguments...
      if ( source_filefolder != null ) {
        for ( int i = 0; i < source_filefolder.length; i++ ) {
          saveSourceRep( rep, id_job, getObjectId(), i, source_filefolder[i] );
          saveDestinationRep( rep, id_job, getObjectId(), i, destination_filefolder[i] );
          rep.saveJobEntryAttribute( id_job, getObjectId(), i, "wildcard", wildcard[i] );
        }
      }
    } catch ( KettleDatabaseException dbe ) {

      throw new KettleException( BaseMessages.getString( PKG, "JobCopyFiles.Error.Exception.UnableSaveRep" )
        + id_job, dbe );
    }
  }

  String[] preprocessfilefilder( String[] folders ) {
    List<String> nfolders = new ArrayList<>();
    if ( folders != null ) {
      for ( int i = 0; i < folders.length; i++ ) {
        nfolders.add( folders[ i ].replace( JobEntryCopyFiles.SOURCE_URL + i + "-", "" )
          .replace( JobEntryCopyFiles.DEST_URL + i + "-", "" ) );
      }
    }
    return nfolders.toArray( new String[ nfolders.size() ] );
  }

  public Result execute( Result previousResult, int nr ) throws KettleException {
    Result result = previousResult;

View on GitHub (pinned to f3058517a1)