pentaho/pentaho-kettle · error · KettleStepException

Unable to clone row while adding rows to the terminator…

Error message

Unable to clone row while adding rows to the terminator buffer

What it means

If a step is configured with a terminator (terminator_rows buffer, used e.g. by 'Abort'/'Injector' style tracking), BaseStep clones each row before adding it to the buffer. A KettleValueException from rowMeta.cloneRow(row) is wrapped in this KettleStepException. It means the current row cannot be duplicated for the terminator buffer.

Solutions

  1. Disable the terminator option on the step if the buffered rows are not needed.
  2. Fix the offending field value/type identified from the chained KettleValueException cause.
  3. Normalize row data upstream (Select values / value conversion) so every field matches its declared type.
  4. Catch KettleStepException around putRow and log the failing row for inspection.

Example fix

// before
step.setTerminator(true); // with rows containing custom objects

// after: either disable terminator or normalize data first
// Add a 'Select values' step converting fields to standard types before putRow
Defensive patterns

Strategy: try-catch

Validate before calling

if (rowMeta.size() != row.length) {
  throw new IllegalArgumentException("row data length does not match metadata");
}

Type guard

boolean isCloneable(Object[] row) {
  return row != null && Arrays.stream(row).allMatch(v -> v == null || v instanceof String || v instanceof Number || v instanceof Date || v instanceof Boolean || v instanceof byte[]);
}

Try / catch

try {
  putRow(rowMeta, row);
} catch (KettleStepException e) {
  if (e.getMessage().contains("terminator buffer")) {
    logError("Row cannot be cloned for terminator buffer: " + Arrays.toString(row), e);
  } else { throw e; }
}

Prevention

When it happens

Trigger: putRow() called on a step with the terminator flag enabled while the row contains a value that RowMeta.cloneRow cannot copy (incompatible value object for declared metadata).

Common situations: Terminating/abort steps downstream combined with rows carrying custom or corrupted value data; hand-constructed rows whose objects do not match the RowMeta value types; plugin version mismatches.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

      try {
        Thread.sleep( 1 );
      } catch ( InterruptedException e ) {
        throw new KettleStepException( e );
      }
    }

    // call all row listeners...
    //
    for ( RowListener listener : rowListeners ) {
      listener.rowWrittenEvent( rowMeta, row );
    }

    // Keep adding to terminator_rows buffer...
    if ( terminator && terminator_rows != null ) {
      try {
        terminator_rows.add( rowMeta.cloneRow( row ) );
      } catch ( KettleValueException e ) {
        throw new KettleStepException( "Unable to clone row while adding rows to the terminator buffer", e );
      }
    }

    if ( stopped.get() ) {
      if ( log.isDebug() ) {
        logDebug( BaseMessages.getString( PKG, "BaseStep.Log.StopPuttingARow" ) );
      }
      stopAll();
      return;
    }

    // Don't distribute or anything, only go to this rowset!
    //
    while ( !rowSet.putRow( rowMeta, row ) ) {
      if ( isStopped() ) {
        break;
      }
    }

View on GitHub (pinned to f3058517a1)