{"record":{"id":"9424490f08cf6336","repo":"pentaho/pentaho-kettle","slug":"denormalisermeta-exception-unabletolocatekeyfield","errorCode":"DenormaliserMeta.Exception.UnableToLocateKeyField","errorMessage":"DenormaliserMeta.Exception.UnableToLocateKeyField","messagePattern":"DenormaliserMeta\\.Exception\\.UnableToLocateKeyField","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/denormaliser/DenormaliserMeta.java","lineNumber":164,"sourceCode":"  }\n\n  public void setDefault() {\n    int sizegroup = 0;\n    int nrfields = 0;\n\n    allocate( sizegroup, nrfields );\n  }\n\n  @Override\n  public void getFields( Bowl bowl, RowMetaInterface row, String name, RowMetaInterface[] info, StepMeta nextStep,\n    VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException {\n\n    // Remove the key value (there will be different entries for each output row)\n    //\n    if ( keyField != null && keyField.length() > 0 ) {\n      int idx = row.indexOfValue( keyField );\n      if ( idx < 0 ) {\n        throw new KettleStepException( BaseMessages.getString(\n          PKG, \"DenormaliserMeta.Exception.UnableToLocateKeyField\", keyField ) );\n      }\n      row.removeValueMeta( idx );\n    } else {\n      throw new KettleStepException( BaseMessages.getString( PKG, \"DenormaliserMeta.Exception.RequiredKeyField\" ) );\n    }\n\n    // Remove all field value(s) (there will be different entries for each output row)\n    //\n    for ( int i = 0; i < denormaliserTargetField.length; i++ ) {\n      String fieldname = denormaliserTargetField[i].getFieldName();\n      if ( fieldname != null && fieldname.length() > 0 ) {\n        int idx = row.indexOfValue( fieldname );\n        if ( idx >= 0 ) {\n          row.removeValueMeta( idx );\n        }\n      } else {\n        throw new KettleStepException( BaseMessages.getString(","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/denormaliser/DenormaliserMeta.java#L146-L182","documentation":"DenormaliserMeta.getFields transforms the input row metadata for the Denormaliser step. The key field (the grouping field) must exist in the incoming stream and is removed from the output row layout. If keyField is set but not found in the row (indexOfValue returns -1), a KettleStepException is thrown with the field name in the message.","triggerScenarios":"getFields (invoked during transformation initialization, e.g. from testGetFields) is given a non-empty keyField that is absent from the incoming RowMetaInterface — row.indexOfValue(keyField) returns -1.","commonSituations":"Upstream step renamed/removed the key field; typo in the Denormaliser 'key field' setting; changing the stream layout with a Select values step and forgetting to update the Denormaliser.","solutions":["Preview the rows entering the Denormaliser and set its 'key field' to a field that actually exists.","Fix upstream renaming/dropping of the key field (Select values, Calculator, etc.).","Re-run the 'Get fields' / verify mapping in the Denormaliser dialog after any upstream change.","If the key field should not exist, note that it is consumed as the grouping key — define it upstream."],"exampleFix":"// before\nkeyField = \"grp_id\"  // upstream renamed it\n// after\nkeyField = \"group_id\" // matches field emitted by the previous step","handlingStrategy":"validation","validationCode":"RowMetaInterface input = previousStep.getOutputRowMeta();\nif (denormMeta.getKeyField() != null && input.indexOfValue(denormMeta.getKeyField()) < 0) {\n  throw new IllegalArgumentException(\"Key field not in input stream: \" + denormMeta.getKeyField());\n}","typeGuard":null,"tryCatchPattern":"try { transMeta.getFields(...); } catch (KettleStepException e) { log.error(\"Denormaliser key field missing: {}\", e.getMessage(), e); }","preventionTips":["Re-check step mappings after renaming/dropping upstream fields.","Preview the stream feeding the Denormaliser before running.","Use Spoon's field propagation rather than typing field names manually."],"tags":["denormaliser","row-field-lookup","stream-metadata"],"backgroundTag":"resource-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"}