pentaho/pentaho-kettle · error · KettleStepException

DenormaliserMeta.Exception.RequiredKeyField

DenormaliserMeta.Exception.RequiredKeyField

Error message

DenormaliserMeta.Exception.RequiredKeyField

What it means

DenormaliserMeta.getFields requires a key field (the field whose distinct values group the rows). When the keyField setting is null or an empty string, the step cannot build its grouping logic and throws a KettleStepException with this message instead of attempting a lookup.

Solutions

  1. Open the Denormaliser step dialog and set the 'key field' to the grouping column.
  2. If using metadata injection, map the key field target in the injection metadata.
  3. Re-apply the step configuration from a working version of the transformation.

Example fix

// before
<key_field></key_field>
// after
<key_field>customer_id</key_field>
Defensive patterns

Strategy: validation

Validate before calling

if (denormMeta.getKeyField() == null || denormMeta.getKeyField().isEmpty()) {
  throw new IllegalArgumentException("Denormaliser key field must be configured");
}

Try / catch

try { transMeta.getFields(...); } catch (KettleStepException e) { log.error("Denormaliser unconfigured: {}", e.getMessage()); }

Prevention

When it happens

Trigger: getFields executes with keyField == null || keyField.length() == 0, i.e. the Denormaliser step was never given a grouping key field (the else-branch of the keyField check).

Common situations: Freshly dropped Denormaliser step left unconfigured; metadata injection mapping omitted the key field; a saved transformation lost the key field setting after a schema/upgrade issue.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/denormaliser/DenormaliserMeta.java:169

    allocate( sizegroup, nrfields );
  }

  @Override
  public void getFields( Bowl bowl, RowMetaInterface row, String name, RowMetaInterface[] info, StepMeta nextStep,
    VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException {

    // Remove the key value (there will be different entries for each output row)
    //
    if ( keyField != null && keyField.length() > 0 ) {
      int idx = row.indexOfValue( keyField );
      if ( idx < 0 ) {
        throw new KettleStepException( BaseMessages.getString(
          PKG, "DenormaliserMeta.Exception.UnableToLocateKeyField", keyField ) );
      }
      row.removeValueMeta( idx );
    } else {
      throw new KettleStepException( BaseMessages.getString( PKG, "DenormaliserMeta.Exception.RequiredKeyField" ) );
    }

    // Remove all field value(s) (there will be different entries for each output row)
    //
    for ( int i = 0; i < denormaliserTargetField.length; i++ ) {
      String fieldname = denormaliserTargetField[i].getFieldName();
      if ( fieldname != null && fieldname.length() > 0 ) {
        int idx = row.indexOfValue( fieldname );
        if ( idx >= 0 ) {
          row.removeValueMeta( idx );
        }
      } else {
        throw new KettleStepException( BaseMessages.getString(
          PKG, "DenormaliserMeta.Exception.RequiredTargetFieldName", ( i + 1 ) + "" ) );
      }
    }

    // Re-add the target fields

View on GitHub (pinned to f3058517a1)