pentaho/pentaho-kettle · error · KettleValueException
Janino.Error.ValueTypeMismatch
Janino.Error.ValueTypeMismatch
Error message
Janino.Error.ValueTypeMismatch
What it means
Thrown by the Janino step's calcFields when a formula's result type does not match the declared (or replaced field's) value type and no automatic Integer->Long conversion applies. Kettle enforces that the Java result class is assignable to the configured ValueMeta type.
Solutions
- Set the formula's 'Value type' to match what the expression returns (e.g. String, BigNumber).
- Cast or convert inside the formula to the expected type (e.g. Long.parseLong(...), new BigDecimal(...)).
- If replacing a field, ensure the output type matches the replaced field's type or use a Select Values type conversion after the step.
- Log the formula result class (see the exception text) to confirm the actual Java type.
Example fix
// before (value type: Integer) return price * qty; // yields BigDecimal // after return (long) (price.doubleValue() * qty);
Defensive patterns
Strategy: try-catch
Validate before calling
// Check declared value type vs. expected Java type ValueMetaInterface vm = ValueMetaFactory.createValueMeta(fn.getValueType()); // e.g. TYPE_STRING expects String results; TYPE_NUMBER expects Double
Type guard
boolean isCompatible(ValueMetaInterface vm, Object result) {
if (result == null) return true;
if (vm.getNativeDataTypeClass().isAssignableFrom(result.getClass())) return true;
return result instanceof Integer && vm.getType() == ValueMetaInterface.TYPE_INTEGER;
} Try / catch
try { row = calcFields(row); } catch (KettleValueException e) { logError("Formula type mismatch: " + e.getMessage()); throw e; } Prevention
- Set Value type immediately when editing a formula.
- Remember Janino arithmetic promotes to Integer/BigDecimal — convert explicitly.
- Test formulas with sample rows in the preview pane.
When it happens
Trigger: getNativeDataTypeClass().isAssignableFrom(result.getClass()) is false and the result is not an Integer for TYPE_INTEGER — e.g. formula returns String/BigDecimal/Double while the field value type is Integer, Number, Date, or Boolean.
Common situations: Changing a formula but leaving the old 'Value type' in the dialog; replacing a field whose type differs from the formula output; Janino returning boxed types like BigDecimal from arithmetic.
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.MixingTypes
- DynamicSQLRow.Exception.TemplateReturnDataTypeError
- ElasticSearchBulk.Error.NoJsonFieldFormat
- ERROR_ARITHMETIC_VALUE
- Function MOD only works with numeric data
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/3c10358797733bfa.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/janino/Janino.java:196
for ( int x = 0; x < argumentIndexes.size(); x++ ) {
int index = argumentIndexes.get( x );
ValueMetaInterface outputValueMeta = data.outputRowMeta.getValueMeta( index );
argumentData[x] = outputValueMeta.convertToNormalStorageType( outputRowData[index] );
}
Object formulaResult = data.expressionEvaluators[i].evaluate( argumentData );
Object value = null;
if ( formulaResult == null ) {
value = null;
} else {
ValueMetaInterface valueMeta = data.returnType[i];
if ( valueMeta.getNativeDataTypeClass().isAssignableFrom( formulaResult.getClass() ) ) {
value = formulaResult;
} else if ( formulaResult instanceof Integer && valueMeta.getType() == ValueMetaInterface.TYPE_INTEGER ) {
value = ( (Integer) formulaResult ).longValue();
} else {
throw new KettleValueException(
BaseMessages.getString( PKG, "Janino.Error.ValueTypeMismatch", valueMeta.getTypeDesc(),
meta.getFormula()[i].getFieldName(), formulaResult.getClass(), meta.getFormula()[i].getFormula() ) );
}
}
// We're done, store it in the row with all the data, including the temporary data...
//
if ( data.replaceIndex[i] < 0 ) {
outputRowData[tempIndex++] = value;
} else {
outputRowData[data.replaceIndex[i]] = value;
}
}
return outputRowData;
} catch ( Exception e ) {
throw new KettleValueException( e );
}View on GitHub (pinned to f3058517a1)