pentaho/pentaho-kettle · error · KettleException
FilterRows.Exception.UnexpectedErrorFoundInEvaluationFuction
FilterRows.Exception.UnexpectedErrorFoundInEvaluationFuction
Error message
FilterRows.Exception.UnexpectedErrorFoundInEvaluationFuction
What it means
FilterRows evaluates its Condition against each incoming row to decide the true/false target. keepRow() catches any Exception thrown during that evaluation, logs the row that failed, and rethrows a KettleException with this message - meaning the filter expression itself blew up while processing a specific row.
Solutions
- Inspect the log line 'Error occurred while filtering rows' + the row dump to identify the offending field/value.
- Check the filter condition's field types vs the actual incoming row metadata (right-click > Show input fields / preview upstream).
- Add a 'Value Mapper'/'If field value is null' or 'Data Grid'-style cleanup step upstream to normalize nulls/types before filtering.
Example fix
// before: filter condition compares field 'amount' (Number) to string '10' // after: upstream add a Select Values step converting 'amount' from String to Number, // or change the condition value type to Number 10
Defensive patterns
Strategy: try-catch
Validate before calling
// Check condition field types match the incoming metadata before running:
for (String field : condition.getUsedFields()) {
ValueMetaInterface vm = prevRowMeta.searchValueMeta(field);
if (vm == null) throw new IllegalStateException("Filter field missing: " + field);
} Try / catch
try {
trans.execute(null);
} catch (KettleException e) {
if (e.getMessage().contains("UnexpectedErrorFoundInEvaluationFuction")) {
log.error("Filter condition failed on a row - check field types/nulls in the logged row dump", e);
}
throw e;
} Prevention
- Normalize nulls and types upstream (Select Values / Value Mapper) before filtering.
- Preview upstream data to spot type drift after upstream changes.
- Keep condition comparisons between fields of matching declared types.
When it happens
Trigger: keepRow() -> condition.evaluate(rowMeta, row) throws: comparing incompatible field types (string vs number), null values against non-null-safe comparisons, or a condition referencing a field whose data changed shape after metadata was cached.
Common situations: Filtering on a numeric field that sometimes receives non-numeric/null data; comparing a date field against a wrongly formatted string; upstream step changed field types after the filter was configured.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Error adding values to row!
- Error during processing a row
- Failed to add Cell Row:
- Failed to process some row
- SalesforceInput.Exception.CanNotReadFromSalesforce
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/6d68732b4e51af64.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/filterrows/FilterRows.java:59
private FilterRowsMeta meta;
private FilterRowsData data;
public FilterRows( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
Trans trans ) {
super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
}
private synchronized boolean keepRow( RowMetaInterface rowMeta, Object[] row ) throws KettleException {
try {
return meta.getCondition().evaluate( rowMeta, row );
} catch ( Exception e ) {
String message =
BaseMessages.getString( PKG, "FilterRows.Exception.UnexpectedErrorFoundInEvaluationFuction" );
logError( message );
logError( BaseMessages.getString( PKG, "FilterRows.Log.ErrorOccurredForRow" ) + rowMeta.getString( row ) );
logError( Const.getStackTracker( e ) );
throw new KettleException( message, e );
}
}
public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {
meta = (FilterRowsMeta) smi;
data = (FilterRowsData) sdi;
boolean keep;
Object[] r = getRow(); // Get next usable row from input rowset(s)!
if ( r == null ) { // no more input to be expected...
setOutputDone();
return false;
}
if ( first ) {
first = false;View on GitHub (pinned to f3058517a1)