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

  1. Convert the offending field to Number/Integer/BigDecimal in a Select values step before multiplying
  2. Fix the field's declared type metadata in the stream
  3. Confirm the string-repetition case (String * Integer) is being routed through multiply(), not multiplyNumeric() directly
  4. 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

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


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)