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
- Disable the terminator option on the step if the buffered rows are not needed.
- Fix the offending field value/type identified from the chained KettleValueException cause.
- Normalize row data upstream (Select values / value conversion) so every field matches its declared type.
- 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
- Disable terminator option when buffered rows are unnecessary
- Normalize row values to standard types upstream
- Verify row objects match declared value metadata
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
- Unable to clone row while copying rows to multiple target…
- AuthenticationManager.ConsumedTypeError
- AvroInput.Error.UnexpectedRecordFieldTypeAtNonExpansionPoint
- BaseStep.SafeMode.Exception.MixingTypes
- Can't encode object of class : className
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)