pentaho/pentaho-kettle · error · KettleException
MultiMergeJoin.Log.UnableToFindReferenceStream
MultiMergeJoin.Log.UnableToFindReferenceStream
Error message
MultiMergeJoin.Log.UnableToFindReferenceStream
What it means
MultiMergeJoin.processFirstRow() iterates its info streams and resolves each input step's metadata. If a stream's StepMeta is null (the configured input step name cannot be resolved to an actual step in the transformation), a KettleException 'UnableToFindReferenceStream' is thrown. The in-code comment notes init() should normally have caught this.
Solutions
- Open the MultiMergeJoin step dialog, verify every listed input step exists and is connected, then re-save
- Fix the transformation XML: correct or remove the stale step reference and re-add the hop
- Recreate the hop in Spoon by dragging from the actual input step to the join
- Validate the TransMeta programmatically before running (transMeta.checkSteps() / verify all hop sources resolve)
Example fix
// before (stale reference in generated metadata) joinMeta.getMainStepName(); // references "inputA" which was renamed to "inputA2" // after transMeta.findStep( "inputA2" ); // update join config to the real step name, reconnect hop, then run
Defensive patterns
Strategy: validation
Validate before calling
for ( String name : joinMeta.getInputStepNames() ) {
if ( transMeta.findStep( name ) == null ) {
throw new IllegalStateException( "MultiMergeJoin references non-existent input step: " + name );
}
}
transMeta.checkSteps(); // also surfaces dangling references Type guard
function allInputsResolve( transMeta, joinMeta ) {
return joinMeta.getInfoStreams().every( s => s.getStepMeta() != null );
} Try / catch
try {
trans.execute( null );
trans.waitUntilFinished();
} catch ( KettleException e ) {
if ( e.getMessage() != null && e.getMessage().contains( "UnableToFindReferenceStream" ) ) {
// fix stale step reference / reconnect hop in transformation metadata
} else { throw e; }
} Prevention
- Avoid hand-editing ktr XML step names; rename via Spoon so references update
- After deleting/renaming any input step, re-check every join that referenced it
- Run checkSteps() validation before execution
- Import transformations with hop verification enabled
When it happens
Trigger: Running a transformation where a MultiMergeJoin input stream's source step name is set but the step does not exist in the transformation graph (e.g. step deleted/renamed after the join was configured), so stream.getStepMeta() returns null.
Common situations: Hand-edited or programmatically generated ktr XML referencing a nonexistent step name; renaming an input step without reconnecting the hop; XML import where hop definitions were lost.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- A deadlock was detected between steps
- AggregateRowsMeta.Exception.UnableToLoadStepInfo
- AppendMeta.Exception.UnableToLoadStepInfo
- At this time we don't support the use of multiple cluster…
- Could not create ValueMetaInterface
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/e98f9b51412a7219.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/multimerge/MultiMergeJoin.java:88
TransHopMeta transHopMeta;
StepIOMetaInterface stepIOMeta = meta.getStepIOMeta();
List<StreamInterface> infoStreams = stepIOMeta.getInfoStreams();
StreamInterface stream;
StepMeta toStepMeta = meta.getParentStepMeta();
StepMeta fromStepMeta;
ArrayList<String> inputStepNameList = new ArrayList<String>();
String[] inputStepNames = meta.getInputSteps();
String inputStepName;
for ( int i = 0; i < infoStreams.size(); i++ ) {
inputStepName = inputStepNames[i];
stream = infoStreams.get( i );
fromStepMeta = stream.getStepMeta();
if ( fromStepMeta == null ) {
//should not arrive here, shoud typically have been caught by init.
throw new KettleException(
BaseMessages.getString( PKG, "MultiMergeJoin.Log.UnableToFindReferenceStream", inputStepName ) );
}
//check the hop
transHopMeta = transMeta.findTransHop( fromStepMeta, toStepMeta, true );
//there is no hop: this is unexpected.
if ( transHopMeta == null ) {
//should not arrive here, shoud typically have been caught by init.
throw new KettleException(
BaseMessages.getString( PKG, "MultiMergeJoin.Log.UnableToFindReferenceStream", inputStepName ) );
} else if ( transHopMeta.isEnabled() ) {
inputStepNameList.add( inputStepName );
} else {
logDetailed( BaseMessages.getString( PKG, "MultiMergeJoin.Log.IgnoringStep", inputStepName ) );
}
}
int streamSize = inputStepNameList.size();
if ( streamSize == 0 ) {View on GitHub (pinned to f3058517a1)