{"record":{"id":"b98d3c344322c71f","repo":"pentaho/pentaho-kettle","slug":"subtraction-can-only-be-done-with-numbers","errorCode":null,"errorMessage":"Subtraction can only be done with numbers!","messagePattern":"Subtraction can only be done with numbers!","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/compatibility/Value.java","lineNumber":2197,"sourceCode":"  public Value minus( byte v ) throws KettleValueException {\n    return minus( new Value( \"tmp\", (long) v ) );\n  }\n\n  public Value minus( Value v ) throws KettleValueException {\n    switch ( getType() ) {\n      case VALUE_TYPE_BIGNUMBER:\n        value.setBigNumber( getBigNumber().subtract( v.getBigNumber() ) );\n        break;\n      case VALUE_TYPE_NUMBER:\n        value.setNumber( getNumber() - v.getNumber() );\n        break;\n      case VALUE_TYPE_INTEGER:\n        value.setInteger( getInteger() - v.getInteger() );\n        break;\n      case VALUE_TYPE_BOOLEAN:\n      case VALUE_TYPE_STRING:\n      default:\n        throw new KettleValueException( \"Subtraction can only be done with numbers!\" );\n    }\n    return this;\n  }\n\n  public Value plus( BigDecimal v ) {\n    return plus( new Value( \"tmp\", v ) );\n  }\n\n  public Value plus( double v ) {\n    return plus( new Value( \"tmp\", v ) );\n  }\n\n  public Value plus( long v ) {\n    return plus( new Value( \"tmp\", v ) );\n  }\n\n  public Value plus( int v ) {\n    return plus( new Value( \"tmp\", (long) v ) );","sourceCodeStart":2179,"sourceCodeEnd":2215,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/compatibility/Value.java#L2179-L2215","documentation":"This KettleValueException is thrown by Value.minus() when subtraction is attempted on a Value whose type is not numeric (Boolean, String, or any other non-numeric VALUE_TYPE). The legacy compatibility Value class only defines arithmetic for Number, Integer, BigNumber, and Date types; anything else is rejected explicitly.","triggerScenarios":"Calling value.minus(other) (or the Kettle formula/calculator step mapping to it) where either operand's VALUE_TYPE is BOOLEAN, STRING, or an unhandled default — e.g. a field read from CSV as String then used directly in a subtraction.","commonSituations":"Input files where numeric columns were inferred as String; a calculator step wired to a text field; type inference changes after an upstream transformation; forgetting to use the 'Fields > Select/Type' conversion before arithmetic.","solutions":["Convert operands to a numeric type first: value.setType( Value.VALUE_TYPE_NUMBER ) after setValue, or use convertString( VALUE_TYPE_NUMBER ).","In transformation design, add a Select Values / Calculator step to set the field type to Integer/Number before subtraction.","Null-check and validate input field metadata (ValueMetaInterface type) before arithmetic.","If the string is a formatted number, parse with a NumberFormat/BigDecimal and store as BigNumber.","Catch KettleValueException around arithmetic to fail fast with a clear field-level message."],"exampleFix":"// before\nValue result = strValue.minus( other ); // throws if strValue is STRING\n// after\nValue num = new Value( \"amount\", strValue.getNumber() ); // or strValue.convertString( Value.VALUE_TYPE_NUMBER )\nValue result = num.minus( other );","handlingStrategy":"type-guard","validationCode":"// before subtraction\nif ( !( a.isNumber() || a.isInteger() || a.isBigNumber() ) ) {\n  a.convertString( Value.VALUE_TYPE_NUMBER );\n}","typeGuard":"boolean isNumericValue( Value v ) {\n  return v != null && ( v.isNumber() || v.isInteger() || v.isBigNumber() );\n}","tryCatchPattern":"try {\n  Value result = a.minus( b );\n} catch ( KettleValueException e ) {\n  throw new IllegalStateException( \"Non-numeric operand for minus(): type=\" + a.getType(), e );\n}","preventionTips":["Force numeric field types with Select Values before arithmetic steps.","Inspect ValueMetaInterface.getType() when building calculator logic.","Parse text numerics with an explicit conversion step, never implicitly.","Watch for type-inference changes after upstream refactors.","Add metadata assertions in transformation unit tests."],"tags":["arithmetic","type-mismatch","value-types"],"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"}