pentaho/pentaho-kettle · error · KettleException

FuzzyMatch.Exception.CouldnotFindLookField

Error message

FuzzyMatch.Exception.CouldnotFindLookField

What it means

FuzzyMatch.readLookupValues validates the info (lookup) stream's row metadata and throws this KettleException when the configured Lookup Field cannot be found in the lookup stream (indexOfValue < 0). It fails fast at the first row instead of silently matching against a missing column.

Solutions

  1. Open the Fuzzy Match step and re-select the Lookup field from the dropdown so it matches the actual lookup-stream column.
  2. Check the step feeding the lookup side of the hop and confirm the column name (case-sensitive) is produced there.
  3. If a variable is used for the field name, verify the variable resolves correctly (add a 'Get Variables' log or use environmentSubstitute debugging).
  4. Re-run after adding the missing column via a Select Values or other step if the field is genuinely required.

Example fix

// before
Lookup field: 'cust_id'
// after (column actually named 'customer_id' in lookup stream)
Lookup field: 'customer_id'
Defensive patterns

Strategy: validation

Validate before calling

// Before the Fuzzy Match step, assert the lookup field exists:
int idx = lookupRowMeta.indexOfValue(lookupFieldName);
if (idx < 0) {
  throw new KettleException("Lookup field not found in lookup stream: " + lookupFieldName);
}

Try / catch

try {
  processRow();
} catch (KettleException e) {
  if (e.getMessage().contains("CouldnotFindLookField")) {
    logError("Check Fuzzy Match lookup field config vs lookup stream layout: " + e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: The Fuzzy Match step's 'Lookup field' setting names a column that does not exist in the second (lookup) input stream when the first lookup row is read in processRow.

Common situations: Typo in the lookup field name; upstream lookup-stream step renamed/removed the column; field was added as environment variable placeholder that didn't resolve; copying a transformation between environments where stream layouts differ.

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


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/d442ea16e5e59533. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/fuzzymatch/FuzzyMatch.java:89

    if ( isDetailed() ) {
      logDetailed( BaseMessages.getString( PKG, "FuzzyMatch.Log.ReadingFromStream" )
        + data.infoStream.getStepname() + "]" );
    }

    boolean firstRun = true;
    // Which row set do we read from?
    //
    RowSet rowSet = findInputRowSet( data.infoStream.getStepname() );
    Object[] rowData = getRowFrom( rowSet ); // rows are originating from "lookup_from"

    while ( rowData != null ) {
      if ( firstRun ) {
        data.infoMeta = rowSet.getRowMeta().clone();
        // Check lookup field
        int indexOfLookupField = data.infoMeta.indexOfValue( environmentSubstitute( meta.getLookupField() ) );
        if ( indexOfLookupField < 0 ) {
          // The field is unreachable !
          throw new KettleException( BaseMessages.getString(
            PKG, "FuzzyMatch.Exception.CouldnotFindLookField", meta.getLookupField() ) );
        }
        data.infoCache = new RowMeta();
        ValueMetaInterface keyValueMeta = data.infoMeta.getValueMeta( indexOfLookupField );
        keyValueMeta.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL );
        data.infoCache.addValueMeta( keyValueMeta );
        // Add key
        data.indexOfCachedFields[0] = indexOfLookupField;

        // Check additional fields
        if ( data.addAdditionalFields ) {
          ValueMetaInterface additionalFieldValueMeta;
          for ( int i = 0; i < meta.getValue().length; i++ ) {
            int fi = i + 1;
            data.indexOfCachedFields[fi] = data.infoMeta.indexOfValue( meta.getValue()[i] );
            if ( data.indexOfCachedFields[fi] < 0 ) {
              // The field is unreachable !
              throw new KettleException( BaseMessages.getString(

View on GitHub (pinned to f3058517a1)