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
- Open the Denormaliser step dialog and set the 'key field' to the grouping column.
- If using metadata injection, map the key field target in the injection metadata.
- 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
- Always configure the grouping key field when adding a Denormaliser step.
- Include the key field target in metadata injection mappings.
- Run transformation verification (Ctrl+V in Spoon) before execution.
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
- DenormaliserMeta.Exception.RequiredTargetFieldName
- DenormaliserMeta.Exception.UnableToLocateKeyField
- ConcatFields.Error.FieldNotFoundInputStream
- ConcatFields.Error.RemainingFieldNotFoundInputStream
- Field name [ ] couldn't be found in the input stream!
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 fieldsView on GitHub (pinned to f3058517a1)