pentaho/pentaho-kettle · error · KettleException
Unable to find step ' ' to read from.
Error message
Unable to find step '{sourceStepName}' to read from. What it means
Thrown by MetaInject.processRow() when the source step name configured for metadata injection does not exist in the injected (child) transformation. MetaInject looks up meta.getSourceStepName() in the generated sub-transformation to attach a row listener; a null lookup means the injection target/source mapping references a step name that isn't there.
Solutions
- Open the source .ktr and confirm a step exists whose name exactly matches the Meta Inject 'source step name' (names are case-sensitive)
- Re-select the source step in the Meta Inject dialog so the mapping is regenerated against the current child transformation
- If the child transformation path comes from a variable, resolve the variable at runtime and verify it points to the intended file
- Re-run 'Load transformation' in the Meta Inject dialog to refresh available step names
Example fix
// before: stale hardcoded name
meta.setSourceStepName('Old Data Grid');
// after: name matching the current child step
meta.setSourceStepName('Data Grid'); Defensive patterns
Strategy: validation
Validate before calling
// Before running, verify the source step exists in the child transformation
TransMeta child = new TransMeta(childKtrPath);
if (child.findStep(meta.getSourceStepName()) == null) {
throw new IllegalStateException("Source step '" + meta.getSourceStepName() + "' not in child ktr");
} Type guard
boolean sourceStepExists(TransMeta child, String name) {
return name != null && !name.isEmpty() && child.findStep(name) != null;
} Try / catch
try {
// run transformation with Meta Inject
} catch (KettleException e) {
if (e.getMessage().contains("Unable to find step")) {
log.error('Stale injection source step: re-map in Meta Inject dialog', e);
} else throw e;
} Prevention
- Re-generate the injection mapping whenever the child .ktr changes
- Treat step names as case-sensitive exact identifiers
- Avoid variable-derived child paths in production; pin explicit paths
- Diff child .ktr changes in version control to catch renamed steps
When it happens
Trigger: Running the Meta Inject step when 'source step name' is set but the target (injected) .ktr has no step with that exact name at copy 0 — typically after the child transformation was renamed, deleted, or its steps were changed.
Common situations: Child .ktr edited/renamed after configuring injection; case-sensitive step name mismatch; pointing the source step to a step in the parent instead of the injected transformation; variable-derived transformation path resolving to a different file.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- BaseStep.Exception.SourceStepToReadFromDoesntExist
- BaseStep.Exception.TargetStepToWriteToDoesntExist
- DeleteMeta.Exception.ConnectionUndefined
- MappingDialog.Exception.SpecifiedStepWasNotFound
- A connection of type PALO is expected
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/eb41e43962c534d4.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/meta-inject/impl/src/main/java/org/pentaho/di/trans/steps/metainject/MetaInject.java:172
} );
injectTrans.prepareExecution( null );
// See if we need to stream some data over...
//
RowProducer rowProducer = null;
if ( data.streaming ) {
rowProducer = injectTrans.addRowProducer( data.streamingTargetStepname, 0 );
}
// Finally, add the mapping transformation to the active sub-transformations
// map in the parent transformation
//
getTrans().addActiveSubTransformation( getStepname(), injectTrans );
if ( !Utils.isEmpty( meta.getSourceStepName() ) ) {
StepInterface stepInterface = injectTrans.getStepInterface( meta.getSourceStepName(), 0 );
if ( stepInterface == null ) {
throw new KettleException( "Unable to find step '" + meta.getSourceStepName() + "' to read from." );
}
stepInterface.addRowListener( new RowAdapter() {
@Override
public void rowWrittenEvent( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
// Just pass along the data as output of this step...
//
MetaInject.this.putRow( rowMeta, row );
}
} );
}
injectTrans.startThreads();
if ( data.streaming ) {
// Deplete all the rows from the parent transformation into the modified transformation
//
RowSet rowSet = findInputRowSet( data.streamingSourceStepname );
if ( rowSet == null ) {View on GitHub (pinned to f3058517a1)