pentaho/pentaho-kettle · error · org.pentaho.di.core.exception.KettleValueException

The 'divide' function only works on numeric data.

Error message

The 'divide' function only works on numeric data.

What it means

This divide() overload (no VariableSpace) supports only TYPE_NUMBER, TYPE_INTEGER, and TYPE_BIGNUMBER; any other value type hits the default branch and throws KettleValueException. Division has no string/boolean fallback, so non-numeric input always fails.

Solutions

  1. Convert both fields to numeric types (Select values / Calculator) before dividing
  2. Correct the stream's field type metadata so it is Number/Integer/BigDecimal
  3. If dividing strings that contain numbers, parse them explicitly first (Str2Num)
  4. Verify upstream steps preserve numeric types

Example fix

// before
Object r = ValueDataUtil.divide(metaStr, "10", metaNum, 2.0); // String input
// after
ValueMetaInterface numMeta = new ValueMetaNumber("a_num");
Object a = numMeta.convertData(metaStr, "10");
Object r = ValueDataUtil.divide(numMeta, a, metaNum, 2.0);
Defensive patterns

Strategy: validation

Validate before calling

// Java: both operands must be numeric for divide
for (ValueMetaInterface m : new ValueMetaInterface[]{metaA, metaB}) {
  int t = m.getType();
  if (!(t == ValueMetaInterface.TYPE_NUMBER || t == ValueMetaInterface.TYPE_INTEGER
     || t == ValueMetaInterface.TYPE_BIGNUMBER)) {
    throw new IllegalArgumentException("divide needs numeric input, got " + m.getTypeDesc());
  }
}

Type guard

boolean isDivideSafe(ValueMetaInterface m) {
  int t = m.getType();
  return t == ValueMetaInterface.TYPE_NUMBER || t == ValueMetaInterface.TYPE_INTEGER
      || t == ValueMetaInterface.TYPE_BIGNUMBER;
}

Try / catch

try {
  result = ValueDataUtil.divide(metaA, dataA, metaB, dataB);
} catch (KettleValueException e) {
  log.error("divide requires numeric operands: " + metaA.getTypeDesc() + "/" + metaB.getTypeDesc());
  throw e;
}

Prevention

When it happens

Trigger: Calling ValueDataUtil.divide(metaA, dataA, metaB, dataB) where either meta is Boolean, String, Date, Binary, or unspecified — the switch has no matching case.

Common situations: Calculator 'A/B' step receiving a String-typed field from CSV; a rate/percent calculation where the numerator was changed to Boolean; type drift after upstream refactoring.

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/7044c28aea9a7341. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:842

    return s.toString();
  }

  @Deprecated
  public static Object divide( ValueMetaInterface metaA, Object dataA, ValueMetaInterface metaB, Object dataB ) throws KettleValueException {
    if ( dataA == null || dataB == null ) {
      return null;
    }

    switch ( metaA.getType() ) {
      case ValueMetaInterface.TYPE_NUMBER:
        return divideDoubles( metaA.getNumber( dataA ), metaB.getNumber( dataB ) );
      case ValueMetaInterface.TYPE_INTEGER:
        return divideLongs( metaA.getInteger( dataA ), metaB.getInteger( dataB ) );
      case ValueMetaInterface.TYPE_BIGNUMBER:
        return divideBigDecimals( metaA.getBigNumber( dataA ), metaB.getBigNumber( dataB ), (MathContext) null );

      default:
        throw new KettleValueException( "The 'divide' function only works on numeric data." );
    }
  }

  public static Object divide( ValueMetaInterface metaA, Object dataA, ValueMetaInterface metaB, Object dataB, VariableSpace space ) throws KettleValueException {
    if ( dataA == null || dataB == null ) {
      return null;
    }

    switch ( metaA.getType() ) {
      case ValueMetaInterface.TYPE_NUMBER:
        return divideDoubles( metaA.getNumber( dataA ), metaB.getNumber( dataB ) );
      case ValueMetaInterface.TYPE_INTEGER:
        return divideLongs( metaA.getInteger( dataA ), metaB.getInteger( dataB ) );
      case ValueMetaInterface.TYPE_BIGNUMBER:
        return divideBigDecimals( metaA.getBigNumber( dataA ), metaB.getBigNumber( dataB ), space );

      default:
        throw new KettleValueException( "The 'divide' function only works on numeric data." );

View on GitHub (pinned to f3058517a1)