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

  1. Ensure the Main stream field and Lookup field have identical ValueMeta types (add a Select Values / type-conversion step to align them).
  2. Read the wrapped cause of the KettleStepException (getMessage/getCause) to identify the underlying failure in getFromCache.
  3. Normalize nulls/empty strings in the match key before the Fuzzy Match step.
  4. 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

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


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)