{"record":{"id":"fc1ae525ffbecd36","repo":"pentaho/pentaho-kettle","slug":"the-multiply-function-only-works-on-numeric-data-optionally","errorCode":null,"errorMessage":"The 'multiply' function only works on numeric data optionally multiplying strings.","messagePattern":"The 'multiply' function only works on numeric data optionally multiplying strings\\.","errorType":"exception","errorClass":"org.pentaho.di.core.exception.KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java","lineNumber":762,"sourceCode":"    if ( ( metaB.isString() && metaA.isNumeric() ) || ( metaB.isNumeric() && metaA.isString() ) ) {\n      return multiplyString( metaA, dataA, metaB, dataB );\n    }\n\n    return multiplyNumeric( metaA, dataA, metaB, dataB );\n  }\n\n  protected static Object multiplyNumeric( ValueMetaInterface metaA, Object dataA, ValueMetaInterface metaB,\n    Object dataB ) throws KettleValueException {\n    switch ( metaA.getType() ) {\n      case ValueMetaInterface.TYPE_NUMBER:\n        return multiplyDoubles( metaA.getNumber( dataA ), metaB.getNumber( dataB ) );\n      case ValueMetaInterface.TYPE_INTEGER:\n        return multiplyLongs( metaA.getInteger( dataA ), metaB.getInteger( dataB ) );\n      case ValueMetaInterface.TYPE_BIGNUMBER:\n        return multiplyBigDecimals( metaA.getBigNumber( dataA ), metaB.getBigNumber( dataB ), null );\n\n      default:\n        throw new KettleValueException(\n          \"The 'multiply' function only works on numeric data optionally multiplying strings.\" );\n    }\n  }\n\n  public static Double multiplyDoubles( Double a, Double b ) {\n    return new Double( a.doubleValue() * b.doubleValue() );\n  }\n\n  public static Long multiplyLongs( Long a, Long b ) {\n    return new Long( a.longValue() * b.longValue() );\n  }\n\n  // Get BigNumber size to be considered in mathematical operations\n  private static int getMaxPrecision( BigDecimal a, BigDecimal b ) {\n    return a.precision() >= b.precision() ? a.precision() : b.precision();\n  }\n\n  // Get BigNumber max scale (length of decimal part)","sourceCodeStart":744,"sourceCodeEnd":780,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java#L744-L780","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nObject r = ValueDataUtil.multiply(metaA, dataA, metaDate, dateVal); // Date input\n// after\nValueMetaInterface numMeta = new ValueMetaNumber(\"n\");\nObject n = numMeta.convertData(metaDate, dateVal);\nObject r = ValueDataUtil.multiply(metaA, dataA, numMeta, n);","handlingStrategy":"validation","validationCode":"// Java: gate multiply on numeric types\nint t = metaB.getType();\nif (!(t == ValueMetaInterface.TYPE_NUMBER || t == ValueMetaInterface.TYPE_INTEGER\n   || t == ValueMetaInterface.TYPE_BIGNUMBER)) {\n  throw new IllegalArgumentException(\"multiply needs numeric input, got \" + metaB.getTypeDesc());\n}","typeGuard":"boolean isMultiplySafe(ValueMetaInterface m) {\n  int t = m.getType();\n  return t == ValueMetaInterface.TYPE_NUMBER || t == ValueMetaInterface.TYPE_INTEGER\n      || t == ValueMetaInterface.TYPE_BIGNUMBER;\n}","tryCatchPattern":"try {\n  result = ValueDataUtil.multiply(metaA, dataA, metaB, dataB);\n} catch (KettleValueException e) {\n  log.error(\"multiply type mismatch: \" + metaA.getTypeDesc() + \" * \" + metaB.getTypeDesc());\n  throw e;\n}","preventionTips":["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"],"tags":["type-mismatch","arithmetic","kettle"],"backgroundTag":"type-mismatch","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}