{"record":{"id":"ccdabcb7c2a116ee","repo":"pentaho/pentaho-kettle","slug":"streamlookup-log-gotrowwithoutkeys","errorCode":null,"errorMessage":"StreamLookup.Log.GotRowWithoutKeys","messagePattern":"StreamLookup\\.Log\\.GotRowWithoutKeys","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/streamlookup/StreamLookup.java","lineNumber":273,"sourceCode":"            // Change the input value to match the lookup value\n            //\n            lu[i] = lookupValue.convertDataCompatible( inputValue, lu[i] );\n          } catch ( KettleValueException e ) {\n            throw new KettleStepException( \"Error converting data while looking up value\", e );\n          }\n        }\n      }\n    }\n\n    Object[] add = null;\n\n    if ( data.hasLookupRows ) {\n      try {\n        if ( meta.getKeystream().length > 0 ) {\n          add = getFromCache( data.cacheKeyMeta, lu );\n        } else {\n   // Just take the first element in the hashtable...\n          throw new KettleStepException( BaseMessages.getString( PKG, \"StreamLookup.Log.GotRowWithoutKeys\" ) );\n        }\n      } catch ( Exception e ) {\n        throw new KettleStepException( e );\n      }\n    }\n\n    if ( add == null ) { // nothing was found, unknown code: add the specified default value...\n      add = data.nullIf;\n    }\n\n    return RowDataUtil.addRowData( row, rowMeta.size(), add );\n  }\n\n  private void addToCache( RowMetaInterface keyMeta, Object[] keyData, RowMetaInterface valueMeta,\n    Object[] valueData ) throws KettleValueException {\n    if ( meta.isMemoryPreservationActive() ) {\n      if ( meta.isUsingSortedList() ) {\n        KeyValue keyValue = new KeyValue( keyData, valueData );","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/streamlookup/StreamLookup.java#L255-L291","documentation":"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.","triggerScenarios":"lookupValues: data.hasLookupRows is true, meta.getKeystream().length == 0, so getFromCache cannot be called and the exception is thrown unconditionally.","commonSituations":"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.","solutions":["Open the StreamLookup step and define at least one key field pair (stream field -> lookup field)","If an unconditional 'first row' lookup is truly intended, restructure using 'Get rows from result' or a different join strategy instead","If building metadata programmatically, call allocateStreams()/setKeystream() and setKeylookup() before running","Re-export/re-save the transformation to regenerate the step metadata if fields were lost"],"exampleFix":"// before (meta XML, no keys)\n<keystream></keystream>\n// after\n<keystream>customer_id</keystream>\n<keylookup>customer_id</keylookup>","handlingStrategy":"validation","validationCode":"if (meta.getKeystream() == null || meta.getKeystream().length == 0) {\n  throw new IllegalStateException(\"StreamLookup requires at least one key field pair\");\n}","typeGuard":"boolean hasKeys(StreamLookupMeta meta) {\n  return meta.getKeystream() != null && meta.getKeystream().length > 0;\n}","tryCatchPattern":"try { processRow(); } catch (KettleStepException e) {\n  if (e.getMessage().contains(\"GotRowWithoutKeys\")) { /* configure key fields */ }\n  throw e;\n}","preventionTips":["Never leave the key mapping table empty in the step dialog","When generating metadata programmatically, always set keystream/keylookup arrays","Validate step configuration before running headless (Kitchen) executions"],"tags":["kettle","pdi","stream-lookup","misconfiguration"],"backgroundTag":"missing-required-argument","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}