pentaho/pentaho-kettle · error · KettleStepException

BaseStep.Exception.SourceStepToReadFromCantRunInMultipleCopies

BaseStep.Exception.SourceStepToReadFromCantRunInMultipleCopies

Error message

BaseStep.Exception.SourceStepToReadFromCantRunInMultipleCopies

What it means

findInputRowSet(String sourceStep) requires the source step to run in a single copy; after confirming it exists, it throws KettleStepException when sourceStepMeta.getCopies() > 1. With multiple copies there are several row sets from that step, so a single name-based lookup is ambiguous.

Solutions

  1. Set the source step's copies to 1 in its dialog (right-click > Change number of copies).
  2. Use the multi-copy-aware overload findInputRowSet(sourceStep, sourceStepCopy, targetStep, targetCopy) and iterate over copies explicitly.
  3. Partition the source step instead of running copies, so a single logical copy is addressable.
  4. In custom code, enumerate row sets via getInputRowSets() rather than resolving one by name.

Example fix

// before
RowSet rs = findInputRowSet("Parallel Source"); // runs 4 copies
// after
for (RowSet rs : getInputRowSets()) { /* consume all copies */ }
Defensive patterns

Strategy: validation

Validate before calling

StepMeta sm = transMeta.findStep(sourceStepName);
if (sm != null && sm.getCopies() > 1) throw new IllegalArgumentException("Step '" + sourceStepName + "' runs " + sm.getCopies() + " copies; use the copy-aware lookup");

Try / catch

try { RowSet rs = findInputRowSet(sourceStepName); } catch (KettleStepException e) { if (e.getMessage().contains("multiple copies")) { logError("Switch to copy-aware row set access"); } throw e; }

Prevention

When it happens

Trigger: Calling findInputRowSet(sourceStep) where the referenced step has 'Copies' set to N>1 or is launched in multiple copies via clustering/variable-driven copy count.

Common situations: User set 'Execute for each row' / copies to parallelize the source; clustered transformation where the source runs on several slaves; a plugin expecting single-copy semantics used against a partitioned source.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java:2402

  /**
   * Find input row set.
   *
   * @param sourceStep the source step
   * @return the row set
   * @throws KettleStepException the kettle step exception
   */
  public RowSet findInputRowSet( String sourceStep ) throws KettleStepException {
    // Check to see that "sourceStep" only runs in a single copy
    // Otherwise you'll see problems during execution.
    //
    StepMeta sourceStepMeta = transMeta.findStep( sourceStep );
    if ( sourceStepMeta == null ) {
      throw new KettleStepException( BaseMessages.getString(
        PKG, "BaseStep.Exception.SourceStepToReadFromDoesntExist", sourceStep ) );
    }

    if ( sourceStepMeta.getCopies() > 1 ) {
      throw new KettleStepException( BaseMessages.getString(
        PKG, "BaseStep.Exception.SourceStepToReadFromCantRunInMultipleCopies", sourceStep, Integer
          .toString( sourceStepMeta.getCopies() ) ) );
    }

    return findInputRowSet( sourceStep, 0, getStepname(), getCopy() );
  }

  /**
   * Find input row set.
   *
   * @param from     the from
   * @param fromcopy the fromcopy
   * @param to       the to
   * @param tocopy   the tocopy
   * @return the row set
   */
  public RowSet findInputRowSet( String from, int fromcopy, String to, int tocopy ) {
    inputRowSetsLock.readLock().lock();

View on GitHub (pinned to f3058517a1)