pentaho/pentaho-kettle · error · KettleStepException
throw new KettleStepException( e );
Error message
throw new KettleStepException( e );
What it means
lookupValues calls getFromCache(row) to find the closest match for the main-stream row's key; any exception thrown inside cache lookup (including KettleExceptions from cached metadata or runtime conversions) is wrapped in a KettleStepException. It is a broad catch-all wrapping failure of the matching/caching path.
Solutions
- Ensure the Main stream field and Lookup field have identical ValueMeta types (add a Select Values / type-conversion step to align them).
- Read the wrapped cause of the KettleStepException (getMessage/getCause) to identify the underlying failure in getFromCache.
- Normalize nulls/empty strings in the match key before the Fuzzy Match step.
- Check that lookup stream rows loaded via readLookupValues match the expected cache schema.
Example fix
// before (main field Integer vs lookup field String) // after: convert main field to String before Fuzzy Match // Select Values step: cust_id -> String // Fuzzy Match: Main stream field: cust_id (String), Lookup field: cust_id (String)
Defensive patterns
Strategy: validation
Validate before calling
// Align types of main and lookup key fields before matching:
ValueMetaInterface main = mainRowMeta.searchValueMeta(mainField);
ValueMetaInterface look = lookupRowMeta.searchValueMeta(lookupField);
if (main.getType() != look.getType()) {
throw new KettleException("Key type mismatch: " + main + " vs " + look);
} Type guard
boolean keysCompatible(ValueMetaInterface a, ValueMetaInterface b) {
return a != null && b != null && a.getType() == b.getType();
} Try / catch
try {
add = getFromCache(row);
} catch (KettleStepException e) {
logError("Fuzzy match cache lookup failed: " + e.getCause(), e);
throw e; // rethrow after logging the wrapped cause
} Prevention
- Make main and lookup key fields the same ValueMeta type before matching.
- Handle null/empty keys explicitly before the Fuzzy Match step.
- Log the cause chain of KettleStepException to find the real failure.
- Test with representative data including edge-case values (nulls, long strings).
When it happens
Trigger: row[indexOfMainField] is non-null but getFromCache throws — e.g. comparing the main value against cached lookup values fails due to incompatible value types, or an internal KettleException propagates from cache data structures.
Common situations: Main field and lookup field have mismatched types (String vs Number) making compareTo fail; cached lookup metadata was altered; unexpected null/typed data variations in the main field.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- AuthenticationManager.ConsumedTypeError
- AvroInput.Error.UnexpectedRecordFieldTypeAtNonExpansionPoint
- BaseStep.SafeMode.Exception.MixingTypes
- Can't encode object of class : className
- Cannot convert value to Base.Array.
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/ac4d72ea75ed6fec.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/fuzzymatch/FuzzyMatch.java:188
getTransMeta().getBowl(), data.outputRowMeta, getStepname(), new RowMetaInterface[] { data.infoMeta }, null,
this, repository, metaStore );
// Check lookup field
data.indexOfMainField = getInputRowMeta().indexOfValue( environmentSubstitute( meta.getMainStreamField() ) );
if ( data.indexOfMainField < 0 ) {
// The field is unreachable !
throw new KettleException( BaseMessages.getString( PKG, "FuzzyMatch.Exception.CouldnotFindMainField", meta
.getMainStreamField() ) );
}
}
Object[] add = null;
if ( row[ data.indexOfMainField ] == null ) {
add = buildEmptyRow();
} else {
try {
add = getFromCache( row );
} catch ( Exception e ) {
throw new KettleStepException( e );
}
}
return RowDataUtil.addRowData( row, rowMeta.size(), add );
}
private void addToCache( Object[] value ) throws KettleException {
try {
data.look.add( value );
} catch ( java.lang.OutOfMemoryError o ) {
// exception out of memory
throw new KettleException( BaseMessages.getString( PKG, "FuzzyMatch.Error.JavaHeap", o.toString() ) );
}
}
private Object[] getFromCache( Object[] keyRow ) throws KettleValueException {
if ( isDebug() ) {
logDebug( BaseMessages.getString( PKG, "FuzzyMatch.Log.ReadingMainStreamRow", getInputRowMeta().getString(
keyRow ) ) );View on GitHub (pinned to f3058517a1)