pentaho/pentaho-kettle · error · KettleException

The number of job entry copies read [

Error message

The number of job entry copies read [

What it means

JobDelegate.dataNodeToElement reads job entry copies from the repository DataNode, adds each to jobMeta, then asserts that the number of job copies in the reconstructed JobMeta equals the expected nrCopies stored on the node. A mismatch means the stored job entry copy list is incomplete or inconsistent with its recorded count, so the delegate refuses to load a partially or corruptly deserialized job.

Solutions

  1. Re-save or restore the job from version control / a backup — the stored copy nodes are inconsistent.
  2. Compare jobMeta.getJobCopies().size() to the stored nrCopies by dumping the job's DataNode; identify the missing copy nodes.
  3. Upgrade both PDI client and Pentaho server to matching versions to rule out serialization drift.
  4. Clear and republish the affected job (delete it from the repository and re-import from a known-good export).
  5. If loading programmatically, catch KettleException and fall back to re-downloading or re-creating the job metadata.

Example fix

// before
JobMeta jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll(); // throws on count mismatch
// after
try {
  jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll();
} catch (KettleException e) {
  if (e.getMessage().startsWith("The number of job entry copies read")) {
    jobMeta = restoreJobFromBackup(jobId);
  } else {
    throw e;
  }
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  JobMeta jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll();
} catch (KettleException e) {
  if (e.getMessage().startsWith("The number of job entry copies read")) {
    // repository content inconsistent -> restore from backup/re-export
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Loading a job from a Pentaho repository whose stored DataNode contains fewer (or more) job-entry copy child nodes than the persisted nrCopies attribute — e.g. interrupted save, concurrent modification, repository serialization/version mismatch between writer and reader.

Common situations: Repository corruption after a failed or aborted save; two PDI clients writing the same job concurrently; restoring content exported from a different PDI/Pentaho version; manual database edits on the repository content tables.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/JobDelegate.java:239

      copy.setNr( (int) copyNode.getProperty( PROP_NR ).getLong() );
      int x = (int) copyNode.getProperty( PROP_GUI_LOCATION_X ).getLong();
      int y = (int) copyNode.getProperty( PROP_GUI_LOCATION_Y ).getLong();
      copy.setLocation( x, y );
      copy.setDrawn( copyNode.getProperty( PROP_GUI_DRAW ).getBoolean() );
      copy.setLaunchingInParallel( copyNode.getProperty( PROP_PARALLEL ).getBoolean() );

      // Read the job entry group attributes map
      if ( jobEntry instanceof JobEntryBase ) {
        AttributesMapUtil.loadAttributesMap( copyNode, (JobEntryBase) jobEntry );
      }

      loadAttributesMap( copyNode, copy );

      jobMeta.addJobEntry( copy );
    }

    if ( jobMeta.getJobCopies().size() != nrCopies ) {
      throw new KettleException( "The number of job entry copies read [" + jobMeta.getJobCopies().size()
          + "] was not the number we expected [" + nrCopies + "]" );
    }

    // Read the notes...
    //
    DataNode notesNode = rootNode.getNode( NODE_NOTES );
    int nrNotes = (int) notesNode.getProperty( PROP_NR_NOTES ).getLong();
    for ( DataNode noteNode : notesNode.getNodes() ) {
      String xml = getString( noteNode, PROP_XML );
      jobMeta
          .addNote( new NotePadMeta( XMLHandler.getSubNode( XMLHandler.loadXMLString( xml ), NotePadMeta.XML_TAG ) ) );
    }
    if ( jobMeta.nrNotes() != nrNotes ) {
      throw new KettleException( "The number of notes read [" + jobMeta.nrNotes()
          + "] was not the number we expected [" + nrNotes + "]" );
    }

    // Read the hops...

View on GitHub (pinned to f3058517a1)