pentaho/pentaho-kettle · error · KettleStepException
TableOutput.Exception.FailedToFindField
Error message
TableOutput.Exception.FailedToFindField
What it means
Immediately after the index check, TableOutput.processRow() re-locates each mapped field with searchValueMeta and clones it into the insert row metadata. If the field cannot be found at all (null), it throws KettleStepException with TableOutput.Exception.FailedToFindField. Functionally the same root cause as FieldRequired (missing field in input row), raised on the lookup branch of the same loop.
Solutions
- Rebuild the TableOutput field mapping from the live stream ('Get Fields' in the step dialog)
- Verify the hop actually carries the expected fields (preview the previous step)
- Remove stale entries from the mapping for fields the upstream no longer produces
- Ensure the previous step always emits a valid row layout, never a stripped RowMeta
Example fix
// before
data.insertRowMeta.addValueMeta( insertValue ); // throws when insValue == null
// after
if ( getInputRowMeta().searchValueMeta( meta.getFieldStream()[i] ) == null ) {
throw new KettleStepException( BaseMessages.getString( PKG,
"TableOutput.Exception.FailedToFindField", meta.getFieldStream()[i] )
+ " — available fields: " + getInputRowMeta().getFieldNames() );
}
data.insertRowMeta.addValueMeta( insertValue ); Defensive patterns
Strategy: validation
Validate before calling
// ensure every database column mapping has a matching stream field before execution
List<String> missing = Arrays.stream( meta.getFieldStream() )
.filter( f -> prevRowMeta.searchValueMeta( f ) == null )
.collect( Collectors.toList() );
if ( !missing.isEmpty() ) {
throw new IllegalStateException( "Fields not found in input stream: " + missing );
} Type guard
boolean allMappedFieldsPresent( RowMetaInterface rowMeta, TableOutputMeta meta ) {
return Arrays.stream( meta.getFieldStream() )
.allMatch( f -> rowMeta.searchValueMeta( f ) != null );
} Try / catch
try {
trans.prepareExecution( null );
} catch ( KettleStepException e ) {
if ( e.getMessage().contains( "TableOutput.Exception.FailedToFindField" ) ) {
// rebuild the TableOutput field mapping from the incoming stream
} else { throw e; }
} Prevention
- Rebuild mappings with 'Get Fields' after any upstream layout change
- Preview the step feeding TableOutput to confirm the row layout
- Remove mappings for dropped fields instead of leaving them stale
- Keep the step order stable; avoid disabling steps that supply mapped fields
When it happens
Trigger: processRow() builds data.insertRowMeta on the first row; searchValueMeta(meta.getFieldStream()[i]) returns null because the incoming row's ValueMeta list contains no field with the mapped stream name — empty or misaligned input row metadata, or a mapping configured for a different layout.
Common situations: TableOutput step connected to a hop whose row layout changed (wrong step order, disabled upstream step); mapping copied from another transformation; fields removed by a preceding filter/select step; kettle converting empty rows to empty RowMeta.
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
- TableOutput.Exception.FieldRequired
- TableOutputDialog.FailedToFindField.Message
- GetXMLData.Exception.CouldnotFindField (localized message…
- MappingInput.Exception.UnableToFindMappedValue
- MappingInput.Exception.UnableToFindMappedValue
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/24ed8bb00d224427.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/tableoutput/TableOutput.java:115
// Cache the position of the compare fields in Row row
//
data.valuenrs = new int[meta.getFieldDatabase().length];
for ( int i = 0; i < meta.getFieldDatabase().length; i++ ) {
data.valuenrs[i] = getInputRowMeta().indexOfValue( meta.getFieldStream()[i] );
if ( data.valuenrs[i] < 0 ) {
throw new KettleStepException( BaseMessages.getString(
PKG, "TableOutput.Exception.FieldRequired", meta.getFieldStream()[i] ) );
}
}
for ( int i = 0; i < meta.getFieldDatabase().length; i++ ) {
ValueMetaInterface insValue = getInputRowMeta().searchValueMeta( meta.getFieldStream()[i] );
if ( insValue != null ) {
ValueMetaInterface insertValue = insValue.clone();
insertValue.setName( meta.getFieldDatabase()[i] );
data.insertRowMeta.addValueMeta( insertValue );
} else {
throw new KettleStepException( BaseMessages.getString(
PKG, "TableOutput.Exception.FailedToFindField", meta.getFieldStream()[i] ) );
}
}
}
}
try {
Object[] outputRowData = writeToTable( getInputRowMeta(), r );
if ( outputRowData != null ) {
putRow( data.outputRowMeta, outputRowData ); // in case we want it go further...
incrementLinesOutput();
}
if ( checkFeedback( getLinesRead() ) ) {
if ( log.isBasic() ) {
logBasic( "linenr " + getLinesRead() );
}
}View on GitHub (pinned to f3058517a1)