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

  1. Set the clustered master step's copies to 1 (let the cluster distribute copies).
  2. Make the master step's copies equal the number of source copies/partitions (nrOfSourceCopies).
  3. 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

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


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)