pentaho/pentaho-kettle · error · KettleException

MergeRows.Exception.InvalidLayoutDetected

MergeRows.Exception.InvalidLayoutDetected

Error message

MergeRows.Exception.InvalidLayoutDetected

What it means

Thrown by the Merge Rows step in processRow when checkInputLayoutValid detects that the reference and compare input streams do not have identical row layouts (same fields, same order/types). Since the message wraps the original KettleRowException, the cause describes the exact mismatch. Merge Rows requires both streams to be structurally identical to compare them.

Solutions

  1. Read the wrapped cause (getCause()) — checkInputLayoutValid's message names the exact field/type/order mismatch.
  2. Preview both input streams and align their field layouts exactly (same fields, same order, same types).
  3. Add a 'Select values' step on each branch to add/rename/reorder fields and convert types so both layouts match.
  4. Use the step's Check/validate feature or the transformation validator before running.

Example fix

// before: compare stream missing 'updated_date'
reference: [id, name, updated_date]
compare:    [id, name]
// after: add Select values step on compare branch to include updated_date (Date)
compare:    [id, name, updated_date]
Defensive patterns

Strategy: validation

Validate before calling

// Java: compare the two input layouts before running
StepMeta mergeRows = transMeta.findStep("Merge Rows");
RowMetaInterface ref = transMeta.getPrevStepFields(mergeRows, 0);
RowMetaInterface cmp = transMeta.getPrevStepFields(mergeRows, 1);
if (!ref.equals(cmp)) {
  throw new IllegalStateException("Merge Rows input layouts differ");
}

Try / catch

try {
  trans.execute(null);
} catch (KettleException e) {
  if (e.getMessage().contains("InvalidLayoutDetected")) {
    // inspect e.getCause() (KettleRowException) for the exact field mismatch
  }
}

Prevention

When it happens

Trigger: processRow fetches one row from each input row set and calls checkInputLayoutValid(data.oneRowSet.getRowMeta(), data.twoRowSet.getRowMeta()); any layout difference (missing field, different type, different field order) throws KettleRowException, which is rethrown as this KettleException.

Common situations: See trigger scenarios.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/mergerows/MergeRows.java:93

      //rowSetWhenIdentical is use in case the comparison is IDENTICAL.
      //this should be the "Comparison" stream but can be the "Reference" stream for backward compatibility (PDI-736)
      String useRefWhenIdenticalVar = Const
        .NVL( System.getProperty( Const.KETTLE_COMPATIBILITY_MERGE_ROWS_USE_REFERENCE_STREAM_WHEN_IDENTICAL ), "N" );
      if ( "N".equalsIgnoreCase( useRefWhenIdenticalVar ) ) {
        //use the reference stream (as per documentation)
        useRefWhenIdentical = false;
      } else {
        //use the comparison stream (for backward compatibility)
        useRefWhenIdentical = true;
      }
      data.one = getRowFrom( data.oneRowSet );
      data.two = getRowFrom( data.twoRowSet );

      try {
        checkInputLayoutValid( data.oneRowSet.getRowMeta(), data.twoRowSet.getRowMeta() );
      } catch ( KettleRowException e ) {
        throw new KettleException( BaseMessages.getString( PKG, "MergeRows.Exception.InvalidLayoutDetected" ), e );
      }

      if ( data.one != null ) {
        // Find the key indexes:
        data.keyNrs = new int[ meta.getKeyFields().length ];
        for ( int i = 0; i < data.keyNrs.length; i++ ) {
          data.keyNrs[ i ] = data.oneRowSet.getRowMeta().indexOfValue( meta.getKeyFields()[ i ] );
          if ( data.keyNrs[ i ] < 0 ) {
            String message =
              BaseMessages.getString( PKG, "MergeRows.Exception.UnableToFindFieldInReferenceStream", meta
                .getKeyFields()[ i ] );
            logError( message );
            throw new KettleStepException( message );
          }
        }
      }

      if ( data.two != null ) {

View on GitHub (pinned to f3058517a1)