pentaho/pentaho-kettle · error · KettleException
Multiple input or output steps are not supported for a…
Error message
Multiple input or output steps are not supported for a single threaded mapping.
What it means
In Mapping.processRow's SingleThreaded branch, a single-threaded mapping (run in the SingleThreaded execution mode) requires at most one Mapping Input and one Mapping Output step. If mappingInputs.length > 1 or mappingOutputs.length > 1, a KettleException is thrown. Single-threaded execution streams everything through one thread and cannot arbitrate between multiple mapping entry/exit points.
Solutions
- Ensure the sub-transformation has exactly one Mapping Input and one Mapping Output step.
- Split the multi-input/multi-output sub-transformation into separate single-threaded mappings.
- Run with the standard execution engine instead of Single Threaded if multiple mapping inputs/outputs are required.
- Prefer the 'Simple Mapping (sub-transformation)' single-input/single-output style when targeting single-threaded mode.
Example fix
// before new Trans(...).execute(null) with TransExecutionMode.SingleThreaded and sub.ktr having 2 MappingInputs // after // sub.ktr: keep 1 MappingInput + 1 MappingOutput, or execute with standard engine
Defensive patterns
Strategy: validation
Validate before calling
// Before enabling Single Threaded execution mode:
long in = subTransMeta.getSteps().stream().filter(s -> s.getStepMeta() instanceof MappingInputMeta).count();
long out = subTransMeta.getSteps().stream().filter(s -> s.getStepMeta() instanceof MappingOutputMeta).count();
if (in > 1 || out > 1) throw new IllegalStateException("SingleThreaded mapping supports max 1 input and 1 output (got " + in + "/" + out + ")"); Try / catch
try {
trans.setTransExecutionMode(...); // SingleThreaded
trans.execute(null);
} catch (KettleException e) {
if (e.getMessage().contains("single threaded mapping")) {
log.error("Mapping topology incompatible with SingleThreaded mode: use 1 input/1 output or standard engine", e);
} else { throw e; }
} Prevention
- Design single-threaded mappings with exactly one Mapping Input and one Mapping Output.
- Split multi-input/output sub-transformations before single-threaded execution.
- Only switch execution modes after auditing mapped sub-transformation topology.
- Document execution-mode constraints next to each reusable sub-transformation.
When it happens
Trigger: Transformation executed with 'Single Threaded' execution mode (e.g. Trans.TransExecutionMode.SINGLE_THREAD) where the mapped sub-transformation declares more than one Mapping Input step or more than one Mapping Output step — checked in processRow's switch on mappingType == SingleThreaded.
Common situations: Reusing an ordinary mapping sub-transf with multiple inputs/outputs inside a single-threaded engine run (used for streaming/low-latency pipelines); switching execution mode to single-threaded without auditing the sub-transf topology.
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
- Mapping.Exception.UnableToInitSingleThreadedTransformation
- MappingDialog.Exception.NoMappingSpecified
- MappingDialog.Exception.OneMappingInputStepRequired
- MappingDialog.Exception.OnlyOneMappingInputStepAllowed
- MappingDialog.Exception.SpecifiedStepWasNotFound
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9e4a84814f9d5488.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/mapping/Mapping.java:221
// Set some statistics from the mapping...
// This will show up in Spoon, etc.
//
Result result = getData().getMappingTrans().getResult();
setErrors( result.getNrErrors() );
setLinesRead( result.getNrLinesRead() );
setLinesWritten( result.getNrLinesWritten() );
setLinesInput( result.getNrLinesInput() );
setLinesOutput( result.getNrLinesOutput() );
setLinesUpdated( result.getNrLinesUpdated() );
setLinesRejected( result.getNrLinesRejected() );
}
return false;
case SingleThreaded:
if ( mappingInputs.length > 1 || mappingOutputs.length > 1 ) {
throw new KettleException(
"Multiple input or output steps are not supported for a single threaded mapping." );
}
// Object[] row = getRow();
// RowMetaInterface rowMeta = getInputRowMeta();
// for (int count=0;count<(data.mappingTransMeta.getSizeRowset()/2) && row!=null;count++) {
// // Pass each row over to the mapping input step, fill the buffer...
//
// mappingInputs[0].getInputRowSets().get(0).putRow(rowMeta, row);
//
// row = getRow();
// }
if ( ( log != null ) && log.isDebug() ) {
List<RowSet> mappingInputRowSets = mappingInputs[0].getInputRowSets();
log.logDebug( "# of input buffers: " + mappingInputRowSets.size() );
if ( mappingInputRowSets.size() > 0 ) {View on GitHub (pinned to f3058517a1)