{"record":{"id":"90424b4d072adf94","repo":"pentaho/pentaho-kettle","slug":"streamlookup-log-fieldnotfound","errorCode":null,"errorMessage":"StreamLookup.Log.FieldNotFound","messagePattern":"StreamLookup\\.Log\\.FieldNotFound","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/streamlookup/StreamLookup.java","lineNumber":409,"sourceCode":"          + \"\" ) );\n      }\n      setOutputDone();\n      return false;\n    }\n\n    if ( first ) {\n      first = false;\n\n      // read the lookup values!\n      data.keynrs = new int[meta.getKeystream().length];\n      data.lookupMeta = new RowMeta();\n      data.convertKeysToNative = new boolean[meta.getKeystream().length];\n\n      for ( int i = 0; i < meta.getKeystream().length; i++ ) {\n        // Find the keynr in the row (only once)\n        data.keynrs[i] = getInputRowMeta().indexOfValue( meta.getKeystream()[i] );\n        if ( data.keynrs[i] < 0 ) {\n          throw new KettleStepException(\n            BaseMessages\n              .getString(\n                PKG,\n                \"StreamLookup.Log.FieldNotFound\", meta.getKeystream()[i], \"\" + getInputRowMeta().getString( r ) ) );\n        } else {\n          if ( log.isDetailed() ) {\n            logDetailed( BaseMessages.getString(\n              PKG, \"StreamLookup.Log.FieldInfo\", meta.getKeystream()[i], \"\" + data.keynrs[i] ) );\n          }\n        }\n\n        data.lookupMeta.addValueMeta( getInputRowMeta().getValueMeta( data.keynrs[i] ).clone() );\n\n        // If we have binary storage data coming in, we convert it to normal data storage.\n        // The storage in the lookup data store is also normal data storage. TODO: enforce normal data storage??\n        //\n        data.convertKeysToNative[i] = getInputRowMeta().getValueMeta( data.keynrs[i] ).isStorageBinaryString();\n      }","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/streamlookup/StreamLookup.java#L391-L427","documentation":"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.","triggerScenarios":"processRow: data.keynrs[i] = getInputRowMeta().indexOfValue(meta.getKeystream()[i]) returns -1 for a key stream field on the main input row.","commonSituations":"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.","solutions":["Re-open the step dialog and re-select the key stream fields from the current main input field list","Insert a 'Select Values' step upstream to guarantee field presence and ordering","Check upstream steps that emit heterogeneous rows and normalize their layout","Fix upstream field renames/deletions introduced after the lookup was configured"],"exampleFix":"// before\n<keystream>old_field</keystream>\n// after\n<keystream>new_field</keystream>","handlingStrategy":"validation","validationCode":"// Row-level guard before lookup\nfor (String ks : meta.getKeystream()) {\n  if (inputRowMeta.indexOfValue(ks) < 0)\n    throw new IllegalArgumentException(\"Key field not on main row: \" + ks);\n}","typeGuard":"boolean rowHasKey(RowMetaInterface rm, String field) { return rm.indexOfValue(field) >= 0; }","tryCatchPattern":"try { processRow(row); } catch (KettleStepException e) {\n  if (e.getMessage().contains(\"FieldNotFound\")) {\n    log.error(\"Key field missing on incoming row: \" + e.getMessage()); setErrors(1L); stopAll();\n  }\n  throw e;\n}","preventionTips":["Normalize row layouts from heterogeneous sources (JSON/XML) before lookup","Add a 'Field exists in stream?' step before StreamLookup on dynamic flows","Keep upstream field names stable; centralize renames"],"tags":["kettle","pdi","stream-lookup","field-not-found"],"backgroundTag":"record-not-found","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"}