pentaho/pentaho-kettle · error · KettleException

Unable to save job entry copy to the repository…

Error message

Unable to save job entry copy to the repository, id_job=id_job

What it means

Wrapper error in KettleDatabaseRepositoryJobEntryDelegate.saveJobEntryCopy(): inserting the job entry copy row (insertJobEntryCopy) or resolving its type id failed while saving a job entry to the repository. The transformation/job id is referenced in the message; the cause is chained to the outer KettleException.

Solutions

  1. Read the wrapped KettleDatabaseException cause for the SQL error and fix it (FK, constraint, permissions)
  2. Ensure the job entry plugin is installed so the R_JOBENTRY_TYPE row/id resolves before the copy insert
  3. Verify repository schema is current for your Pentaho version
  4. Retry the save once DB connectivity is restored; avoid leaving the repository connection half-open

Example fix

// before: saving with a plugin that is not installed
repository.save(jobMeta, VERSION_COMMENT, null);
// after: check plugin availability first
if (JobEntryLoader.getInstance().findPluginWithId(entry.getPluginId()) == null) {
  throw new IllegalStateException("Install plugin id=" + entry.getPluginId() + " before saving");
}
repository.save(jobMeta, VERSION_COMMENT, null);
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Calling saveJobEntryCopy where insertJobEntryCopy (or the preceding entry/type inserts) throws KettleDatabaseException — e.g. FK violation on id_job or id_jobentry_type, constraint failure, connection drop.

Common situations: Saving a job whose job entry plugin type is not registered (missing plugin jar), repository schema missing tables, DB read-only/permissions, network interruption during job save.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryJobEntryDelegate.java:243

      // Get the entry type...
      //
      ObjectId id_jobentry_type = getJobEntryTypeID( entry.getPluginId() );

      // Oops, not found: update the repository!
      if ( id_jobentry_type == null ) {
        repository.updateJobEntryTypes();

        // Try again!
        id_jobentry_type = getJobEntryTypeID( entry.getPluginId() );
      }

      // Save the entry copy..
      //
      copy.setObjectId( insertJobEntryCopy( id_job, id_jobentry, id_jobentry_type, copy.getNr(), copy
        .getLocation().x, copy.getLocation().y, copy.isDrawn(), copy.isLaunchingInParallel() ) );

    } catch ( KettleDatabaseException dbe ) {
      throw new KettleException( "Unable to save job entry copy to the repository, id_job=" + id_job, dbe );
    }
  }

  @SuppressWarnings( "deprecation" )
  private void compatibleEntrySaveRep( JobEntryInterface entry, Repository repository, ObjectId id_job ) throws KettleException {
    entry.saveRep( repository, id_job );
  }

  public synchronized ObjectId insertJobEntry( ObjectId id_job, JobEntryBase jobEntryBase ) throws KettleException {
    ObjectId id = repository.connectionDelegate.getNextJobEntryID();

    ObjectId id_jobentry_type = getJobEntryTypeID( jobEntryBase.getPluginId() );

    log.logDebug( "ID_JobEntry_type = " + id_jobentry_type + " for type = [" + jobEntryBase.getPluginId() + "]" );

    RowMetaAndData table = new RowMetaAndData();

    table.addValue( new ValueMetaInteger(

View on GitHub (pinned to f3058517a1)