pentaho/pentaho-kettle · error · KettleStepException

StreamLookup.Log.GotRowWithoutKeys

Error message

StreamLookup.Log.GotRowWithoutKeys

What it means

If the lookup stream contained rows but the step was configured with zero key stream fields, there is no key to look up; when cache rows exist the step cannot pick a match and throws the GotRowWithoutKeys message. This indicates a misconfigured step (no keys defined) at runtime.

Solutions

  1. Open the StreamLookup step and define at least one key field pair (stream field -> lookup field)
  2. If an unconditional 'first row' lookup is truly intended, restructure using 'Get rows from result' or a different join strategy instead
  3. If building metadata programmatically, call allocateStreams()/setKeystream() and setKeylookup() before running
  4. Re-export/re-save the transformation to regenerate the step metadata if fields were lost

Example fix

// before (meta XML, no keys)
<keystream></keystream>
// after
<keystream>customer_id</keystream>
<keylookup>customer_id</keylookup>
Defensive patterns

Strategy: validation

Validate before calling

if (meta.getKeystream() == null || meta.getKeystream().length == 0) {
  throw new IllegalStateException("StreamLookup requires at least one key field pair");
}

Type guard

boolean hasKeys(StreamLookupMeta meta) {
  return meta.getKeystream() != null && meta.getKeystream().length > 0;
}

Try / catch

try { processRow(); } catch (KettleStepException e) {
  if (e.getMessage().contains("GotRowWithoutKeys")) { /* configure key fields */ }
  throw e;
}

Prevention

When it happens

Trigger: lookupValues: data.hasLookupRows is true, meta.getKeystream().length == 0, so getFromCache cannot be called and the exception is thrown unconditionally.

Common situations: Transformation saved with the key mapping table empty; a programmatic caller built StreamLookupMeta without setting keystream/keylookup pairs; metadata lost during transformation migration between PDI versions.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — 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/ccdabcb7c2a116ee. Report an issue: GitHub.

Appendix: source

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

            // Change the input value to match the lookup value
            //
            lu[i] = lookupValue.convertDataCompatible( inputValue, lu[i] );
          } catch ( KettleValueException e ) {
            throw new KettleStepException( "Error converting data while looking up value", e );
          }
        }
      }
    }

    Object[] add = null;

    if ( data.hasLookupRows ) {
      try {
        if ( meta.getKeystream().length > 0 ) {
          add = getFromCache( data.cacheKeyMeta, lu );
        } else {
   // Just take the first element in the hashtable...
          throw new KettleStepException( BaseMessages.getString( PKG, "StreamLookup.Log.GotRowWithoutKeys" ) );
        }
      } catch ( Exception e ) {
        throw new KettleStepException( e );
      }
    }

    if ( add == null ) { // nothing was found, unknown code: add the specified default value...
      add = data.nullIf;
    }

    return RowDataUtil.addRowData( row, rowMeta.size(), add );
  }

  private void addToCache( RowMetaInterface keyMeta, Object[] keyData, RowMetaInterface valueMeta,
    Object[] valueData ) throws KettleValueException {
    if ( meta.isMemoryPreservationActive() ) {
      if ( meta.isUsingSortedList() ) {
        KeyValue keyValue = new KeyValue( keyData, valueData );

View on GitHub (pinned to f3058517a1)