{"record":{"id":"8abe4e40f166eea7","repo":"pentaho/pentaho-kettle","slug":"basestep-safemode-exception-mixingtypes","errorCode":"BaseStep.SafeMode.Exception.MixingTypes","errorMessage":"BaseStep.SafeMode.Exception.MixingTypes","messagePattern":"BaseStep\\.SafeMode\\.Exception\\.MixingTypes","errorType":"validation","errorClass":"KettleRowException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java","lineNumber":2187,"sourceCode":"    //\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      }\n    }\n  }\n\n  /**\n   * Gets the row from.\n   *\n   * @param rowSet the row set","sourceCodeStart":2169,"sourceCodeEnd":2205,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java#L2169-L2205","documentation":"safeModeChecking compares ValueMetaInterface.getType() positionally; if the Kettle value type (String, Integer, Date, Number, ...) at position i differs between the reference row and the incoming row, KettleRowException is thrown. Field names match but the data types change between rows.","triggerScenarios":"Safe mode enabled; a step emits a field as e.g. ValueMetaInteger on the first row and ValueMetaString on a later row, typically because object class of the value differs and the row meta is rebuilt per row.","commonSituations":"UDJE/JavaScript steps that sometimes return a String and sometimes a Number for the same field; CSV/table inputs with mixed-type columns and dynamic type inference; a lookup returning null-vs-typed values that rebuild the meta.","solutions":["Explicitly declare the field type once and convert values to it before putRow (e.g. always convertNumberToString) instead of deriving type from the Java object.","Pre-create the output RowMetaInterface in the step's init/processRow and reuse it for every row.","In table/CSV inputs, set explicit column types in the step dialog rather than relying on inference.","Add a 'Value Mapper' or 'Select values' metadata tab to force the expected type before the failing step."],"exampleFix":"// before\nrowMeta.addValueMeta(new ValueMeta(name, data.getClass())); // type varies per row\n// after\nrowMeta.addValueMeta(new ValueMeta(name, ValueMetaInterface.TYPE_STRING)); // fixed type","handlingStrategy":"validation","validationCode":"for (int i = 0; i < rowMeta.size(); i++) {\n  if (rowMeta.getValueMeta(i).getType() != referenceMeta.getValueMeta(i).getType())\n    throw new IllegalStateException(\"Type mismatch at field \" + rowMeta.getValueMeta(i).getName());\n}","typeGuard":null,"tryCatchPattern":"try { putRow(outputRowMeta, row); } catch (KettleRowException e) { if (e.getMessage().contains(\"MixingTypes\")) { logError(\"Field type changed between rows; coerce values\"); } throw e; }","preventionTips":["Declare output field types explicitly in getFields(), not from data","Reuse a single prebuilt RowMetaInterface for all rows","Convert values with valueMeta.convertData before putRow","Set explicit types in CSV/table input dialogs"],"tags":["kettle","pentaho","safe-mode","type-mismatch","row-metadata"],"backgroundTag":"type-mismatch","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"}