pentaho/pentaho-kettle · error · KettleStepException
StringOperations.Exception.FieldRequired
Error message
StringOperations.Exception.FieldRequired
What it means
StringOperations throws this KettleStepException in processRow() when a field configured for a string operation cannot be found in the incoming row. indexOfValue() returned -1 for one of meta.getFieldInStream() entries, so the step cannot locate the value to transform.
Solutions
- Fix the field name in the String Operations step dialog to match the actual stream field exactly
- Restore the field in the upstream step that was renamed/removed
- Preview the input stream to confirm available field names and re-map
- If fields are dynamic, add a guard (e.g. User Defined Java Expression or filter) before this step
Example fix
// before <field><in_stream_name>emial</in_stream_name><in_stream_trim>...</field> // after <field><in_stream_name>email</in_stream_name><in_stream_trim>...</field>
Defensive patterns
Strategy: validation
Validate before calling
// validate field presence before execution
RowMetaInterface input = transMeta.getPrevStepFields(stepMeta);
for (String f : sopMeta.getFieldInStream()) {
if (input.indexOfValue(f) < 0) {
throw new IllegalStateException("Field not found in stream: " + f);
}
} Try / catch
try {
trans.execute(null);
trans.waitUntilFinished();
} catch (KettleException e) {
if (e.getMessage().contains("StringOperations.Exception.FieldRequired")) {
// re-map the missing field in the step dialog, then re-run
}
} Prevention
- Preview the incoming stream to confirm exact field names
- Keep step field mappings in sync when renaming upstream fields
- Avoid dynamic field dropping upstream without updating this step
- Use case-consistent field naming across the transformation
When it happens
Trigger: On the first processed row when getInputRowMeta().indexOfValue(meta.getFieldInStream()[i]) < 0 — the configured input field name does not exist in the upstream row layout.
Common situations: Upstream field renamed or dropped; connecting the step to a different hop than intended; case-sensitive name mismatch; metadata injected at runtime differs from design time.
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
- StringCut.Exception.FieldRequired
- ConcatFields.Error.FieldNotFoundInputStream
- ConcatFields.Error.TargetFieldNotFoundOutputStream
- Field '' was not found in step's input fields
- FileExists.Exception.CouldnotFindField
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/f5b3821050c2b37c.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/stringoperations/StringOperations.java:234
setOutputDone();
return false;
}
if ( first ) {
first = false;
// What's the format of the output row?
data.outputRowMeta = getInputRowMeta().clone();
data.inputFieldsNr = data.outputRowMeta.size();
meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
metaStore );
data.nrFieldsInStream = meta.getFieldInStream().length;
data.inStreamNrs = new int[data.nrFieldsInStream];
for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {
data.inStreamNrs[i] = getInputRowMeta().indexOfValue( meta.getFieldInStream()[i] );
if ( data.inStreamNrs[i] < 0 ) { // couldn't find field!
throw new KettleStepException( BaseMessages.getString( PKG, "StringOperations.Exception.FieldRequired", meta
.getFieldInStream()[i] ) );
}
// check field type
if ( !getInputRowMeta().getValueMeta( data.inStreamNrs[i] ).isString() ) {
throw new KettleStepException( BaseMessages.getString( PKG, "StringOperations.Exception.FieldTypeNotString",
meta.getFieldInStream()[i] ) );
}
}
data.outStreamNrs = new String[data.nrFieldsInStream];
for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {
data.outStreamNrs[i] = meta.getFieldOutStream()[i];
}
// Keep track of the trim operators locally for a very small
// optimization.
data.trimOperators = new String[data.nrFieldsInStream];
for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {View on GitHub (pinned to f3058517a1)