pentaho/pentaho-kettle · error · KettleStepException

MergeRowsMeta.Exception.FlagFieldNotSpecified

MergeRowsMeta.Exception.FlagFieldNotSpecified

Error message

MergeRowsMeta.Exception.FlagFieldNotSpecified

What it means

MergeRowsMeta.getFields() builds the output row layout for the Merge Rows step and appends a string flag field that marks each row as 'identical', 'changed', 'new', or 'deleted'. If the flag field name is empty or null, the step cannot produce valid output rows, so it throws a KettleStepException with 'FlagFieldNotSpecified'.

Solutions

  1. Open the Merge Rows step dialog and set the 'Flag field name' to a non-empty value, then re-save and rerun
  2. Programmatically call mergeRowsMeta.setFlagField( "flagField" ) before executing
  3. Inspect the transformation XML/ktr (or repository attributes) and add the flag field entry
  4. Add a pre-execution metadata validation that fails early with a clear message

Example fix

// before
MergeRowsMeta meta = new MergeRowsMeta();
meta.allocate();
// flagField never set -> KettleStepException at getFields
// after
MergeRowsMeta meta = new MergeRowsMeta();
meta.setFlagField( "mergeFlag" );
meta.allocate();
Defensive patterns

Strategy: validation

Validate before calling

MergeRowsMeta meta = (MergeRowsMeta) stepMeta.getStepMetaInterface();
if ( meta.getFlagField() == null || meta.getFlagField().trim().isEmpty() ) {
  throw new IllegalArgumentException( "Merge Rows step requires a non-empty flag field name" );
}

Type guard

function hasFlagField( meta ) {
  return meta != null && typeof meta.getFlagField === 'function'
    && typeof meta.getFlagField() === 'string' && meta.getFlagField().length > 0;
}

Try / catch

try {
  transMeta.execute( args );
} catch ( KettleStepException e ) {
  if ( e.getMessage() != null && e.getMessage().contains( "FlagFieldNotSpecified" ) ) {
    // open step config and set the flag field name
  } else { throw e; }
}

Prevention

When it happens

Trigger: Executing a transformation whose Merge Rows step has an empty 'flag field' setting, i.e. setFlagField was never called or the UI field was left blank, causing Utils.isEmpty(flagField) to be true during getFields (row layout resolution at execution time).

Common situations: Transformation XML/repository metadata missing the flagfield attribute; programmatically constructed TransMeta where MergeRowsMeta.setFlagField() was forgotten; upgrading a transformation where the flag field was cleared.

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/8509b8e887bb2feb. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/mergerows/MergeRowsMeta.java:296

  @Override
  public void getFields( Bowl bowl, RowMetaInterface r, String name, RowMetaInterface[] info, StepMeta nextStep,
    VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException {
    // We don't have any input fields here in "r" as they are all info fields.
    // So we just merge in the info fields.
    //
    if ( info != null ) {
      boolean found = false;
      for ( int i = 0; i < info.length && !found; i++ ) {
        if ( info[i] != null ) {
          r.mergeRowMeta( info[i], name );
          found = true;
        }
      }
    }

    if ( Utils.isEmpty( flagField ) ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "MergeRowsMeta.Exception.FlagFieldNotSpecified" ) );
    }
    ValueMetaInterface flagFieldValue = new ValueMetaString( flagField );
    flagFieldValue.setOrigin( name );
    r.addValueMeta( flagFieldValue );

  }

  @Override
  public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta,
    RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space,
    Repository repository, IMetaStore metaStore ) {
    CheckResult cr;

    List<StreamInterface> infoStreams = getStepIOMeta().getInfoStreams();
    StreamInterface referenceStream = infoStreams.get( 0 );
    StreamInterface compareStream = infoStreams.get( 1 );

    if ( referenceStream.getStepname() != null && compareStream.getStepname() != null ) {

View on GitHub (pinned to f3058517a1)