pentaho/pentaho-kettle · error · org.pentaho.di.core.exception.KettleValueException
The 'multiply' function only works on numeric data…
Error message
The 'multiply' function only works on numeric data optionally multiplying strings.
What it means
ValueDataUtil.multiplyNumeric implements '*' and supports only TYPE_NUMBER, TYPE_INTEGER, and TYPE_BIGNUMBER (string repetition handled earlier in multiply()). Any other meta type reaches the default branch and throws KettleValueException with this message.
Solutions
- Convert the offending field to Number/Integer/BigDecimal in a Select values step before multiplying
- Fix the field's declared type metadata in the stream
- Confirm the string-repetition case (String * Integer) is being routed through multiply(), not multiplyNumeric() directly
- Check upstream schema changes if this worked previously
Example fix
// before
Object r = ValueDataUtil.multiply(metaA, dataA, metaDate, dateVal); // Date input
// after
ValueMetaInterface numMeta = new ValueMetaNumber("n");
Object n = numMeta.convertData(metaDate, dateVal);
Object r = ValueDataUtil.multiply(metaA, dataA, numMeta, n); Defensive patterns
Strategy: validation
Validate before calling
// Java: gate multiply on numeric types
int t = metaB.getType();
if (!(t == ValueMetaInterface.TYPE_NUMBER || t == ValueMetaInterface.TYPE_INTEGER
|| t == ValueMetaInterface.TYPE_BIGNUMBER)) {
throw new IllegalArgumentException("multiply needs numeric input, got " + metaB.getTypeDesc());
} Type guard
boolean isMultiplySafe(ValueMetaInterface m) {
int t = m.getType();
return t == ValueMetaInterface.TYPE_NUMBER || t == ValueMetaInterface.TYPE_INTEGER
|| t == ValueMetaInterface.TYPE_BIGNUMBER;
} Try / catch
try {
result = ValueDataUtil.multiply(metaA, dataA, metaB, dataB);
} catch (KettleValueException e) {
log.error("multiply type mismatch: " + metaA.getTypeDesc() + " * " + metaB.getTypeDesc());
throw e;
} Prevention
- Explicitly declare numeric types at stream sources (CSV/table input)
- Use Select values metadata conversion before Calculator multiply
- Watch for Date/Boolean fields accidentally wired into multiplication
- Add type checks in transformation unit tests
When it happens
Trigger: Calling ValueDataUtil.multiply / multiplyNumeric with a meta type other than the three numeric ones — e.g. Boolean, Date, Binary, or unknown type — after the string-multiply path did not apply.
Common situations: Calculator 'A*B' fed a Date or Boolean field; a parsed field fell back to type Unknown; schema drift from an upstream table/CSV changed column types.
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
- The 'divide' function only works on numeric data.
- The 'plus' function only works on numeric data and Strings.
- BaseStep.SafeMode.Exception.MixingTypes
- Division can only be done with numeric data!
- DynamicSQLRow.Exception.TemplateReturnDataTypeError
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/fc1ae525ffbecd36.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:762
if ( ( metaB.isString() && metaA.isNumeric() ) || ( metaB.isNumeric() && metaA.isString() ) ) {
return multiplyString( metaA, dataA, metaB, dataB );
}
return multiplyNumeric( metaA, dataA, metaB, dataB );
}
protected static Object multiplyNumeric( ValueMetaInterface metaA, Object dataA, ValueMetaInterface metaB,
Object dataB ) throws KettleValueException {
switch ( metaA.getType() ) {
case ValueMetaInterface.TYPE_NUMBER:
return multiplyDoubles( metaA.getNumber( dataA ), metaB.getNumber( dataB ) );
case ValueMetaInterface.TYPE_INTEGER:
return multiplyLongs( metaA.getInteger( dataA ), metaB.getInteger( dataB ) );
case ValueMetaInterface.TYPE_BIGNUMBER:
return multiplyBigDecimals( metaA.getBigNumber( dataA ), metaB.getBigNumber( dataB ), null );
default:
throw new KettleValueException(
"The 'multiply' function only works on numeric data optionally multiplying strings." );
}
}
public static Double multiplyDoubles( Double a, Double b ) {
return new Double( a.doubleValue() * b.doubleValue() );
}
public static Long multiplyLongs( Long a, Long b ) {
return new Long( a.longValue() * b.longValue() );
}
// Get BigNumber size to be considered in mathematical operations
private static int getMaxPrecision( BigDecimal a, BigDecimal b ) {
return a.precision() >= b.precision() ? a.precision() : b.precision();
}
// Get BigNumber max scale (length of decimal part)View on GitHub (pinned to f3058517a1)