pentaho/pentaho-kettle · error · KettleException
TransSplitter.Clustering.CopyNumberStep
TransSplitter.Clustering.CopyNumberStep
Error message
TransSplitter.Clustering.CopyNumberStep
What it means
During splitOriginalTransformation, when generating the master copy of a clustered step, Kettle checks that the master step's copy count is 1 or equals the number of source copies. Any other combination produces an unsupported copy layout, and a localized message built from key 'TransSplitter.Clustering.CopyNumberStep' is thrown.
Solutions
- Set the clustered master step's copies to 1 (let the cluster distribute copies).
- Make the master step's copies equal the number of source copies/partitions (nrOfSourceCopies).
- Remove the manual 'Change number of copies to start' setting on the step and rely on cluster/schema-driven copying.
Example fix
// before masterStepMeta.setCopies(3); // mismatch with 2 source copies // after masterStepMeta.setCopies(1);
Defensive patterns
Strategy: validation
Validate before calling
int nrSource = calculateStepCopies(sourceStepMeta);
int masterCopies = masterStepMeta.getCopies();
if (masterCopies != 1 && masterCopies != nrSource) {
masterStepMeta.setCopies(1);
} Prevention
- Leave clustered steps at copies=1 unless matching the source copy count
- Re-check copy settings after changing partitioning
- Document why a step has multiple copies
When it happens
Trigger: splitOriginalTransformation() encounters a clustered master step where masterStep.getCopies() is neither 1 nor equal to nrOfSourceCopies (e.g. copies=3 while the source step runs 2 copies across slaves).
Common situations: Setting a fixed 'copies' value of 2+ on a clustered step in Spoon; changing the source step's partitioning/copy count after the clustered step's copies were tuned to an older value.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by a…
- A server socket allocation always has to accompanied by a…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/4e41c26d219bdf7c.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/cluster/TransSplitter.java:572
//
// Verify the partitioning for this slave step.
// It's running in 1 or more copies depending on the number of partitions
// Get the number of target partitions...
//
StepPartitioningMeta previousStepPartitioningMeta = previousStep.getStepPartitioningMeta();
PartitionSchema previousPartitionSchema = previousStepPartitioningMeta.getPartitionSchema();
int nrOfSourceCopies = determineNrOfStepCopies( sourceSlaveServer, previousStep );
// Verify that the number of copies is equal to the number of slaves or 1
// FIXME check this code, it no longer is relevant after the change to use determineNrOfStepCopies().
// It probably wasn't working before either.
//
if ( masterStep.getCopies() != 1 && masterStep.getCopies() != nrOfSourceCopies ) {
// this case might be handled correctly later
String message = BaseMessages.getString( PKG, "TransSplitter.Clustering.CopyNumberStep", nrSlavesNodes,
previousStep.getName(), masterStep.getName() );
throw new KettleException( message );
}
// Add the required remote input and output steps to make the partitioning a reality.
//
for ( int sourceCopyNr = 0; sourceCopyNr < nrOfSourceCopies; sourceCopyNr++ ) {
// The masterStepCopy number is increasing for each remote copy on each slave.
// This makes the master distribute to each copy of the slave properly.
// There is a check above to make sure that the master has either 1 copy or the same as slave*copies
Integer masterStepCopyNr = masterStepCopyNumbers.poll();
if ( masterStepCopyNr == null ) {
masterStepCopyNr = 0;
}
// We open a port on the various slave servers...
// So the source is the slave server, the target the master.
//
int port =
getPort(View on GitHub (pinned to f3058517a1)