pentaho/pentaho-kettle · error · KettleStepException

StreamLookup.Log.FieldNotFound

Error message

StreamLookup.Log.FieldNotFound

What it means

During processRow, each main-stream row's key values are located by name; if a configured key stream field is missing from the actual input row, the step throws FieldNotFound including the field name and the row's string representation. Unlike the metadata-time check, this fires on row-level input where getInputRowMeta() lacks the field.

Solutions

  1. Re-open the step dialog and re-select the key stream fields from the current main input field list
  2. Insert a 'Select Values' step upstream to guarantee field presence and ordering
  3. Check upstream steps that emit heterogeneous rows and normalize their layout
  4. Fix upstream field renames/deletions introduced after the lookup was configured

Example fix

// before
<keystream>old_field</keystream>
// after
<keystream>new_field</keystream>
Defensive patterns

Strategy: validation

Validate before calling

// Row-level guard before lookup
for (String ks : meta.getKeystream()) {
  if (inputRowMeta.indexOfValue(ks) < 0)
    throw new IllegalArgumentException("Key field not on main row: " + ks);
}

Type guard

boolean rowHasKey(RowMetaInterface rm, String field) { return rm.indexOfValue(field) >= 0; }

Try / catch

try { processRow(row); } catch (KettleStepException e) {
  if (e.getMessage().contains("FieldNotFound")) {
    log.error("Key field missing on incoming row: " + e.getMessage()); setErrors(1L); stopAll();
  }
  throw e;
}

Prevention

When it happens

Trigger: processRow: data.keynrs[i] = getInputRowMeta().indexOfValue(meta.getKeystream()[i]) returns -1 for a key stream field on the main input row.

Common situations: Main stream fields changed dynamically (different row layouts from JSON/XML input); field removed by a Filter/Select Values step; upstream step failed and produced fallback rows without the field.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/streamlookup/StreamLookup.java:409

          + "" ) );
      }
      setOutputDone();
      return false;
    }

    if ( first ) {
      first = false;

      // read the lookup values!
      data.keynrs = new int[meta.getKeystream().length];
      data.lookupMeta = new RowMeta();
      data.convertKeysToNative = new boolean[meta.getKeystream().length];

      for ( int i = 0; i < meta.getKeystream().length; i++ ) {
        // Find the keynr in the row (only once)
        data.keynrs[i] = getInputRowMeta().indexOfValue( meta.getKeystream()[i] );
        if ( data.keynrs[i] < 0 ) {
          throw new KettleStepException(
            BaseMessages
              .getString(
                PKG,
                "StreamLookup.Log.FieldNotFound", meta.getKeystream()[i], "" + getInputRowMeta().getString( r ) ) );
        } else {
          if ( log.isDetailed() ) {
            logDetailed( BaseMessages.getString(
              PKG, "StreamLookup.Log.FieldInfo", meta.getKeystream()[i], "" + data.keynrs[i] ) );
          }
        }

        data.lookupMeta.addValueMeta( getInputRowMeta().getValueMeta( data.keynrs[i] ).clone() );

        // If we have binary storage data coming in, we convert it to normal data storage.
        // The storage in the lookup data store is also normal data storage. TODO: enforce normal data storage??
        //
        data.convertKeysToNative[i] = getInputRowMeta().getValueMeta( data.keynrs[i] ).isStorageBinaryString();
      }

View on GitHub (pinned to f3058517a1)