pentaho/pentaho-kettle · error · KettleRowException

BaseStep.SafeMode.Exception.MixingTypes

BaseStep.SafeMode.Exception.MixingTypes

Error message

BaseStep.SafeMode.Exception.MixingTypes

What it means

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.

Solutions

  1. 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.
  2. Pre-create the output RowMetaInterface in the step's init/processRow and reuse it for every row.
  3. In table/CSV inputs, set explicit column types in the step dialog rather than relying on inference.
  4. Add a 'Value Mapper' or 'Select values' metadata tab to force the expected type before the failing step.

Example fix

// before
rowMeta.addValueMeta(new ValueMeta(name, data.getClass())); // type varies per row
// after
rowMeta.addValueMeta(new ValueMeta(name, ValueMetaInterface.TYPE_STRING)); // fixed type
Defensive patterns

Strategy: validation

Validate before calling

for (int i = 0; i < rowMeta.size(); i++) {
  if (rowMeta.getValueMeta(i).getType() != referenceMeta.getValueMeta(i).getType())
    throw new IllegalStateException("Type mismatch at field " + rowMeta.getValueMeta(i).getName());
}

Try / catch

try { putRow(outputRowMeta, row); } catch (KettleRowException e) { if (e.getMessage().contains("MixingTypes")) { logError("Field type changed between rows; coerce values"); } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

    //
    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() ) );
        }
      }
    }
  }

  /**
   * Gets the row from.
   *
   * @param rowSet the row set

View on GitHub (pinned to f3058517a1)