pentaho/pentaho-kettle · error · KettleRowException
BaseStep.SafeMode.Exception.MixingStorageTypes
BaseStep.SafeMode.Exception.MixingStorageTypes
Error message
BaseStep.SafeMode.Exception.MixingStorageTypes
What it means
safeModeChecking compares ValueMetaInterface.getStorageType() positionally; Kettle stores values either as normal Java objects (STORAGE_TYPE_NORMAL) or indexed/binary variants, and if the storage metadata differs between the reference row and the incoming row, KettleRowException is thrown. Same name, type, and arity — but the internal storage representation changed.
Solutions
- Normalize the storage metadata in the producing step: clone the ValueMetaInterface and call setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL) before putRow.
- Insert a 'Select values' step (metadata tab) which re-materializes values into normal storage between the mismatching steps.
- Update the plugin step to always build ValueMeta objects with consistent storage metadata in getFields().
- As a diagnostic, log rowMeta.toStringMeta() on both sides to see which field's storage metadata differs.
Example fix
// before ValueMeta vm = (ValueMeta) referenceValue.clone(); // keeps indexed storage // after ValueMeta vm = (ValueMeta) referenceValue.clone(); vm.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);
Defensive patterns
Strategy: validation
Validate before calling
for (int i = 0; i < rowMeta.size(); i++) {
if (rowMeta.getValueMeta(i).getStorageType() != referenceMeta.getValueMeta(i).getStorageType())
throw new IllegalStateException("Storage type mismatch at field " + rowMeta.getValueMeta(i).getName());
} Try / catch
try { putRow(outputRowMeta, row); } catch (KettleRowException e) { if (e.getMessage().contains("MixingStorageTypes")) { logError("Storage metadata differs; normalize with Select values"); } throw e; } Prevention
- Clone value metas from the declared layout, then override only what you need
- Call setStorageType(STORAGE_TYPE_NORMAL) when building metas from lookups
- Insert a Select values step to re-materialize storage between mixed sources
- Log toStringMeta() of both layouts when debugging
When it happens
Trigger: Safe mode enabled; a step emits a row whose ValueMeta has a different storage metadata (e.g. STORAGE_TYPE_INDEXED from a dropdown lookup vs STORAGE_TYPE_NORMAL from a computed value) at position i.
Common situations: Mixing rows coming from a lookup step that returns indexed value metas with rows generated inline; plugin steps that clone value metas but override storage metadata inconsistently; serialization round-trips altering storage metadata.
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
- BaseStep.SafeMode.Exception.DoubleFieldnames
- BaseStep.SafeMode.Exception.MixingLayout
- BaseStep.SafeMode.Exception.MixingTypes
- BaseStep.SafeMode.Exception.VaryingSize
- SalesforceUpsert.FieldNotFound
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/f875fc8b7ea59137.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java:2193
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
* @return the row from
* @throws KettleStepException the kettle step exception
*/
public Object[] getRowFrom( RowSet rowSet ) throws KettleStepException {
return getRowHandler().getRowFrom( rowSet );
}View on GitHub (pinned to f3058517a1)