pentaho/pentaho-kettle · error · KettleValueException

Multiplication can only be done with numbers or a number…

Error message

Multiplication can only be done with numbers or a number and a string!

What it means

This KettleValueException is thrown by Value.multiply() when neither operand is a Number, Integer, or BigNumber and the operands don't form the supported number×string case (repeating a string n times). Multiplication in the legacy Value class supports numeric multiplication and string repetition; all other type combinations are rejected.

Solutions

  1. Convert operands to numeric types (convertString( VALUE_TYPE_NUMBER ) / setInteger / setNumber) before multiplying.
  2. In the transformation, insert a Calculator/Select Values step to coerce fields to Number or Integer first.
  3. If string repetition was intended (number × string), ensure exactly one operand is numeric and the other is a String.
  4. Validate input field metadata types before arithmetic and fail early with a descriptive message.
  5. Catch KettleValueException to log both operands' types and values for diagnosis.

Example fix

// before
Value area = widthStr.multiply( heightStr ); // STRING x STRING -> throws
// after
widthStr.convertString( Value.VALUE_TYPE_NUMBER );
heightStr.convertString( Value.VALUE_TYPE_NUMBER );
Value area = widthStr.multiply( heightStr );
Defensive patterns

Strategy: type-guard

Validate before calling

// before multiply
boolean aNum = a.isNumber() || a.isInteger() || a.isBigNumber();
boolean bNum = b.isNumber() || b.isInteger() || b.isBigNumber();
if ( !aNum && !bNum ) throw new IllegalArgumentException( "At least one operand must be numeric" );

Type guard

boolean canMultiply( Value x, Value y ) {
  boolean xNum = x != null && ( x.isNumber() || x.isInteger() || x.isBigNumber() );
  boolean yNum = y != null && ( y.isNumber() || y.isInteger() || y.isBigNumber() );
  return xNum && yNum || ( xNum && y.isString() ) || ( yNum && x.isString() );
}

Try / catch

try {
  Value product = a.multiply( b );
} catch ( KettleValueException e ) {
  throw new IllegalStateException( "Unsupported multiply operands: " + a.getType() + " x " + b.getType(), e );
}

Prevention

When it happens

Trigger: value.multiply(other) where operands are e.g. BOOLEAN×anything, STRING×STRING, or DATE×anything — typically two string fields multiplied, or a boolean produced by a formula used in multiplication.

Common situations: Two text columns from CSV multiplied directly; boolean flags used in calculations without conversion; calculator step mis-wired to non-numeric hops; type inference regressions after upstream changes.

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/277b82d56da0c1fc. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/compatibility/Value.java:2348

        s.setLength( 0 );
      } else {
        for ( int i = 1; i < n; i++ ) {
          s.append( append );
        }
      }

      setValue( s );
    } else if ( isBigNumber() || v.isBigNumber() ) {
      // big numbers
      setValue( ValueDataUtil.multiplyBigDecimals( getBigNumber(), v.getBigNumber(), null ) );
    } else if ( isNumber() || v.isNumber() ) {
      // numbers
      setValue( getNumber() * v.getNumber() );
    } else if ( isInteger() || v.isInteger() ) {
      // integers
      setValue( getInteger() * v.getInteger() );
    } else {
      throw new KettleValueException( "Multiplication can only be done with numbers or a number and a string!" );
    }
    return this;
  }

  // FUNCTIONS!!

  // implement the ABS function, arguments in args[]
  public Value abs() throws KettleValueException {
    if ( isNull() ) {
      return this;
    }

    if ( isBigNumber() ) {
      setValue( getBigNumber().abs() );
    } else if ( isNumber() ) {
      setValue( Math.abs( getNumber() ) );
    } else if ( isInteger() ) {
      setValue( Math.abs( getInteger() ) );

View on GitHub (pinned to f3058517a1)