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
- Re-save or restore the job from version control / a backup — the stored copy nodes are inconsistent.
- Compare jobMeta.getJobCopies().size() to the stored nrCopies by dumping the job's DataNode; identify the missing copy nodes.
- Upgrade both PDI client and Pentaho server to matching versions to rule out serialization drift.
- Clear and republish the affected job (delete it from the repository and re-import from a known-good export).
- 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
- Avoid concurrent edits of the same job by multiple PDI clients.
- Always let PDI save jobs; never edit repository storage manually.
- Keep PDI client and Pentaho server on matching versions.
- Keep export (.kjb) backups so corrupt jobs can be re-imported.
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
- The number of hops read [
- The number of notes read [
- AbsSecurityProvider.ERROR_0002_UNABLE_TO_ACCESS_IS_ALLOWED
- AddSequenceMeta.Exception.UnableToReadStepInfo
- AddSequenceMeta.Exception.UnableToSaveStepInfo
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)