pentaho/pentaho-kettle · error · KettleException
Could not find field in stream
Error message
Could not find field in stream
What it means
While emitting each field entry into the SQL*Loader control file, the loader looks up each mapped stream field name in the row's value metadata (rm.indexOfValue). A negative index means a field listed in the step's field mapping does not exist in the actual incoming stream, so the control file cannot be built consistently.
Solutions
- Open the step mapping tab and re-select fields (click 'Get fields') so mappings match the current upstream stream.
- Rename the mapping entry or the upstream field so names match exactly (case- and whitespace-sensitive).
- Insert/fix a 'Select values' or upstream step so the missing field is actually produced.
- Preview rows immediately before the loader step to confirm the field is present, then re-save the step.
Example fix
// before: mapping references old name <field><stream_name>cust_name</stream_name><table_column>NAME</table_column></field> // after: matches renamed upstream field <field><stream_name>customer_name</stream_name><table_column>NAME</table_column></field>
Defensive patterns
Strategy: validation
Validate before calling
// Java: confirm every mapped stream field exists in the incoming row meta
RowMetaInterface inputRowMeta = ...; // from getStepIOMeta / preview
for (String f : meta.getFieldStream()) {
if (inputRowMeta.indexOfValue(f) < 0) {
throw new IllegalStateException("Mapped stream field missing upstream: " + f);
}
} Try / catch
try {
trans.execute(null);
} catch (KettleException e) {
if (String.valueOf(e.getMessage()).startsWith("Could not find field")) {
// log offending field name and re-open step mapping
}
} Prevention
- Re-run 'Get fields' whenever an upstream step changes schema.
- Avoid manual edits of field names in the ktr XML.
- Keep field names case-consistent end to end.
- Use a 'Select values' step as an explicit contract right before the loader.
When it happens
Trigger: meta.getFieldStream()[i] is not present in the input row metadata when getControlFileContents runs via createControlFile (indexOfValue returns < 0).
Common situations: An upstream step was renamed or deleted a field after the mapping was created; field names differ by case or whitespace; a 'Select values' step removed the column; the ktr was edited manually and the mapping drifted from the real stream.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Could not find field
- InsertUpdate.Exception.FieldRequired
- JsonOutput.Exception.FieldNotFound
- MergeJoin.Exception.UnableToFindFieldInReferenceStream
- SymmetricCryptoTrans.Exception.CouldnotFindField
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/a1cfb7d69577e638.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/oracle-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/orabulkloader/OraBulkLoader.java:262
.append( Const.CR ).append( '(' );
String[] streamFields = meta.getFieldStream();
String[] tableFields = meta.getFieldTable();
String[] dateMask = meta.getDateMask();
if ( streamFields == null || streamFields.length == 0 ) {
throw new KettleException( "No fields defined to load to database" );
}
for ( int i = 0; i < streamFields.length; i++ ) {
if ( i != 0 ) {
contents.append( ", " ).append( Const.CR );
}
contents.append( dm.quoteField( tableFields[i] ) );
int pos = rm.indexOfValue( streamFields[i] );
if ( pos < 0 ) {
throw new KettleException( "Could not find field " + streamFields[i] + " in stream" );
}
ValueMetaInterface v = rm.getValueMeta( pos );
switch ( v.getType() ) {
case ValueMetaInterface.TYPE_STRING:
if ( v.getLength() > 255 ) {
contents.append( " CHAR(" ).append( v.getLength() ).append( ")" );
} else {
contents.append( " CHAR" );
}
break;
case ValueMetaInterface.TYPE_INTEGER:
case ValueMetaInterface.TYPE_NUMBER:
case ValueMetaInterface.TYPE_BIGNUMBER:
break;
case ValueMetaInterface.TYPE_DATE:
if ( OraBulkLoaderMeta.DATE_MASK_DATE.equals( dateMask[i] ) ) {
contents.append( " DATE 'yyyy-mm-dd'" );
} else if ( OraBulkLoaderMeta.DATE_MASK_DATETIME.equals( dateMask[i] ) ) {View on GitHub (pinned to f3058517a1)