pentaho/pentaho-kettle · error · KettleStepException
TableOutput.Exception.FieldRequired
Error message
TableOutput.Exception.FieldRequired
What it means
In TableOutput.processRow(), before writing rows the step caches the index of each configured stream field in the incoming row. If a field named in 'Field to insert' (fieldStream) is not present in the input row (indexOfValue < 0), it throws KettleStepException with TableOutput.Exception.FieldRequired. This is a configuration/data-shape mismatch: the mapping references a field the stream does not deliver.
Solutions
- Open the TableOutput step and correct 'Field to insert' mapping to match actual upstream fields
- Use 'Get Fields' to rebuild the mapping from the incoming stream
- Fix the upstream step (SQL/Select Values/CSV) so it emits the expected field name
- Check field-name case and whitespace — matching is exact via indexOfValue
Example fix
// before
String[] fieldStream = meta.getFieldStream(); // contains 'CUST_ID' but stream has 'custid'
// after
String[] fieldStream = Arrays.stream( meta.getFieldStream() )
.map( f -> getInputRowMeta().searchValueMeta( f ) != null ? f
: findCaseInsensitive( getInputRowMeta(), f ) )
.toArray( String[]::new ); Defensive patterns
Strategy: validation
Validate before calling
// validate the mapping against the live input row before executing
Set<String> streamFields = new HashSet<>( Arrays.asList( prevStepFields.getFieldNames() ) );
for ( String f : meta.getFieldStream() ) {
if ( !streamFields.contains( f ) ) {
throw new IllegalStateException( "Mapped field missing from input stream: " + f );
}
} Type guard
boolean mappingIsValid( RowMetaInterface rowMeta, TableOutputMeta meta ) {
return Arrays.stream( meta.getFieldStream() )
.allMatch( f -> rowMeta.indexOfValue( f ) >= 0 );
} Try / catch
try {
trans.startExecution();
} catch ( KettleStepException e ) {
if ( e.getMessage().contains( "TableOutput.Exception.FieldRequired" ) ) {
// open TableOutput mapping and re-sync with upstream fields
} else { throw e; }
} Prevention
- Run 'Get Fields' in the TableOutput dialog whenever upstream steps change
- Preview upstream steps before executing the transformation
- Keep field names case-consistent end to end
- Avoid renaming fields with Select Values downstream of an existing mapping without updating it
When it happens
Trigger: processRow() receives a row whose RowMeta lacks one of the fields listed in the step's field mapping (meta.getFieldStream()[i]), typically on the first row after init; occurs whenever upstream steps are changed after the TableOutput mapping was configured.
Common situations: Renaming or deleting an upstream field without updating TableOutput's mapping; a Select Values step dropping the field; case-sensitive name mismatch between mapping and stream; reusing a saved transformation against a changed source table/query.
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.FailedToFindField
- 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/fef197d9917ed81b.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/tableoutput/TableOutput.java:103
data.outputRowMeta = getInputRowMeta().clone();
meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
metaStore );
if ( !meta.specifyFields() ) {
// Just take the input row
data.insertRowMeta = getInputRowMeta().clone();
} else {
data.insertRowMeta = new RowMeta();
//
// 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] ) );
}
}
}
}
View on GitHub (pinned to f3058517a1)