pentaho/pentaho-kettle · error · KettleRowException

BaseStep.SafeMode.Exception.MixingLayout

BaseStep.SafeMode.Exception.MixingLayout

Error message

BaseStep.SafeMode.Exception.MixingLayout

What it means

safeModeChecking walks fields positionally; if the field name at position i in the incoming row does not (case-insensitively) match the reference row's field name at i, KettleRowException is thrown. Same field count but fields are in different order or named differently — the row layouts are being mixed.

Solutions

  1. Make the producing step emit fields in a deterministic order (use a List, not a Map, for field construction).
  2. Insert a 'Select values' step before the failing step to enforce a canonical field order.
  3. Check for multiple previous hops feeding the step and align both branches' column order.
  4. If a plugin upgrade reordered columns, pin the previous plugin version or update downstream mappings.

Example fix

// before
Map<String,Object> m = new HashMap<>(); // iteration order varies
// after
List<Object> ordered = Arrays.asList(name, value); // fixed positional order
Defensive patterns

Strategy: validation

Validate before calling

for (int i = 0; i < rowMeta.size(); i++) {
  if (!rowMeta.getValueMeta(i).getName().equalsIgnoreCase(referenceMeta.getValueMeta(i).getName()))
    throw new IllegalStateException("Field order mismatch at position " + i);
}

Try / catch

try { trans.startThreads(); } catch (KettleException e) { if (e.getCause() instanceof KettleRowException && e.getCause().getMessage().contains("MixingLayout")) { logError("Field order differs between rows"); } throw e; }

Prevention

When it happens

Trigger: Safe mode enabled; rows of equal size but with reordered or renamed fields arrive at a step after the reference row was captured (e.g. a step emits [a,b] first then [b,a]).

Common situations: Steps that build rows from a HashMap/unordered Map whose iteration order varies; two branches of a transformation merged with different column orders into the same step; a plugin version change that reordered output fields.

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/75df9853c7b80b34. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java:2180

   * @param rowMeta          the row meta
   * @throws KettleRowException the kettle row exception
   */
  public static void safeModeChecking( RowMetaInterface referenceRowMeta, RowMetaInterface rowMeta )
    throws KettleRowException {
    // See if the row we got has the same layout as the reference row.
    // First check the number of fields
    //
    if ( referenceRowMeta.size() != rowMeta.size() ) {
      throw new KettleRowException( BaseMessages.getString( PKG, "BaseStep.SafeMode.Exception.VaryingSize", ""
        + referenceRowMeta.size(), "" + rowMeta.size(), rowMeta.toString() ) );
    } else {
      // Check field by field for the position of the names...
      for ( int i = 0; i < referenceRowMeta.size(); i++ ) {
        ValueMetaInterface referenceValue = referenceRowMeta.getValueMeta( i );
        ValueMetaInterface compareValue = rowMeta.getValueMeta( i );

        if ( !referenceValue.getName().equalsIgnoreCase( compareValue.getName() ) ) {
          throw new KettleRowException( BaseMessages.getString(
            PKG, "BaseStep.SafeMode.Exception.MixingLayout", "" + ( i + 1 ), referenceValue.getName()
              + " " + referenceValue.toStringMeta(), compareValue.getName()
              + " " + compareValue.toStringMeta() ) );
        }

        if ( referenceValue.getType() != compareValue.getType() ) {
          throw new KettleRowException( BaseMessages.getString( PKG, "BaseStep.SafeMode.Exception.MixingTypes", ""
            + ( i + 1 ), referenceValue.getName() + " " + referenceValue.toStringMeta(), compareValue.getName()
            + " " + compareValue.toStringMeta() ) );
        }

        if ( referenceValue.getStorageType() != compareValue.getStorageType() ) {
          throw new KettleRowException( BaseMessages.getString(
            PKG, "BaseStep.SafeMode.Exception.MixingStorageTypes", "" + ( i + 1 ), referenceValue.getName()
              + " " + referenceValue.toStringMeta(), compareValue.getName()
              + " " + compareValue.toStringMeta() ) );
        }
      }

View on GitHub (pinned to f3058517a1)