{"record":{"id":"75df9853c7b80b34","repo":"pentaho/pentaho-kettle","slug":"basestep-safemode-exception-mixinglayout","errorCode":"BaseStep.SafeMode.Exception.MixingLayout","errorMessage":"BaseStep.SafeMode.Exception.MixingLayout","messagePattern":"BaseStep\\.SafeMode\\.Exception\\.MixingLayout","errorType":"validation","errorClass":"KettleRowException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java","lineNumber":2180,"sourceCode":"   * @param rowMeta          the row meta\n   * @throws KettleRowException the kettle row exception\n   */\n  public static void safeModeChecking( RowMetaInterface referenceRowMeta, RowMetaInterface rowMeta )\n    throws KettleRowException {\n    // See if the row we got has the same layout as the reference row.\n    // First check the number of fields\n    //\n    if ( referenceRowMeta.size() != rowMeta.size() ) {\n      throw new KettleRowException( BaseMessages.getString( PKG, \"BaseStep.SafeMode.Exception.VaryingSize\", \"\"\n        + referenceRowMeta.size(), \"\" + rowMeta.size(), rowMeta.toString() ) );\n    } else {\n      // Check field by field for the position of the names...\n      for ( int i = 0; i < referenceRowMeta.size(); i++ ) {\n        ValueMetaInterface referenceValue = referenceRowMeta.getValueMeta( i );\n        ValueMetaInterface compareValue = rowMeta.getValueMeta( i );\n\n        if ( !referenceValue.getName().equalsIgnoreCase( compareValue.getName() ) ) {\n          throw new KettleRowException( BaseMessages.getString(\n            PKG, \"BaseStep.SafeMode.Exception.MixingLayout\", \"\" + ( i + 1 ), referenceValue.getName()\n              + \" \" + referenceValue.toStringMeta(), compareValue.getName()\n              + \" \" + compareValue.toStringMeta() ) );\n        }\n\n        if ( referenceValue.getType() != compareValue.getType() ) {\n          throw new KettleRowException( BaseMessages.getString( PKG, \"BaseStep.SafeMode.Exception.MixingTypes\", \"\"\n            + ( i + 1 ), referenceValue.getName() + \" \" + referenceValue.toStringMeta(), compareValue.getName()\n            + \" \" + compareValue.toStringMeta() ) );\n        }\n\n        if ( referenceValue.getStorageType() != compareValue.getStorageType() ) {\n          throw new KettleRowException( BaseMessages.getString(\n            PKG, \"BaseStep.SafeMode.Exception.MixingStorageTypes\", \"\" + ( i + 1 ), referenceValue.getName()\n              + \" \" + referenceValue.toStringMeta(), compareValue.getName()\n              + \" \" + compareValue.toStringMeta() ) );\n        }\n      }","sourceCodeStart":2162,"sourceCodeEnd":2198,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java#L2162-L2198","documentation":"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.","triggerScenarios":"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]).","commonSituations":"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.","solutions":["Make the producing step emit fields in a deterministic order (use a List, not a Map, for field construction).","Insert a 'Select values' step before the failing step to enforce a canonical field order.","Check for multiple previous hops feeding the step and align both branches' column order.","If a plugin upgrade reordered columns, pin the previous plugin version or update downstream mappings."],"exampleFix":"// before\nMap<String,Object> m = new HashMap<>(); // iteration order varies\n// after\nList<Object> ordered = Arrays.asList(name, value); // fixed positional order","handlingStrategy":"validation","validationCode":"for (int i = 0; i < rowMeta.size(); i++) {\n  if (!rowMeta.getValueMeta(i).getName().equalsIgnoreCase(referenceMeta.getValueMeta(i).getName()))\n    throw new IllegalStateException(\"Field order mismatch at position \" + i);\n}","typeGuard":null,"tryCatchPattern":"try { trans.startThreads(); } catch (KettleException e) { if (e.getCause() instanceof KettleRowException && e.getCause().getMessage().contains(\"MixingLayout\")) { logError(\"Field order differs between rows\"); } throw e; }","preventionTips":["Build rows from ordered collections (List), never HashMap iteration","Use a Select values step to canonicalize field order after merges","Keep both branches of a merge aligned on column order","Re-check plugins after upgrades for changed field order"],"tags":["kettle","pentaho","safe-mode","row-metadata","column-order"],"backgroundTag":"schema-validation-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}