{"record":{"id":"ad555c2142140357","repo":"apache/cassandra","slug":"a-nan-cannot-be-converted-into-a-decimal","errorCode":null,"errorMessage":"A NaN cannot be converted into a decimal","messagePattern":"A NaN cannot be converted into a decimal","errorType":"validation","errorClass":"NumberFormatException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/DecimalType.java","lineNumber":352,"sourceCode":"\n    /**\n     * Converts the specified number into a {@link BigDecimal}.\n     *\n     * @param number the value to convert\n     * @return the converted value\n     */\n    protected BigDecimal toBigDecimal(Number number)\n    {\n        if (number instanceof BigDecimal)\n            return (BigDecimal) number;\n\n        if (number instanceof BigInteger)\n            return new BigDecimal((BigInteger) number);\n\n        double d = number.doubleValue();\n\n        if (Double.isNaN(d))\n            throw new NumberFormatException(\"A NaN cannot be converted into a decimal\");\n\n        if (Double.isInfinite(d))\n            throw new NumberFormatException(\"An infinite number cannot be converted into a decimal\");\n\n        return BigDecimal.valueOf(d);\n    }\n\n    @Override\n    public ByteBuffer add(Number left, Number right)\n    {\n        return decompose(toBigDecimal(left).add(toBigDecimal(right), MAX_PRECISION));\n    }\n\n    @Override\n    public ByteBuffer substract(Number left, Number right)\n    {\n        return decompose(toBigDecimal(left).subtract(toBigDecimal(right), MAX_PRECISION));\n    }","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/DecimalType.java#L334-L370","documentation":"DecimalType.toBigDecimal converts any Number operand to BigDecimal for arithmetic (add/subtract/multiply/mod, operand selection); Java's BigDecimal cannot represent NaN, so a Number whose doubleValue() is NaN triggers this NumberFormatException.","triggerScenarios":"Calling DecimalType.add/substract/multiply/mod/leftOperand/rightOperand with an operand such as Double.NaN (e.g. computed as 0.0/0.0) reaching toBigDecimal.","commonSituations":"Floating-point computations upstream producing NaN stored in a double column then mixed with decimal arithmetic; JSON input containing NaN tokens.","solutions":["Validate operands with Double.isNaN(d) before the arithmetic call","Replace NaN with null (or a sentinel) rather than passing it to decimal operations","Fix the upstream calculation that produces NaN"],"exampleFix":"// before\ndecimalType.add(left, right); // left may be NaN\n// after\nif (!Double.isNaN(left.doubleValue()) && !Double.isNaN(right.doubleValue()))\n    decimalType.add(left, right);","handlingStrategy":"type-guard","validationCode":"if (Double.isNaN(x.doubleValue()) || Double.isNaN(y.doubleValue())) throw new IllegalArgumentException(\"NaN operand not allowed in decimal arithmetic\");","typeGuard":"boolean isFiniteNumber(Number n) { double d = n.doubleValue(); return !Double.isNaN(d) && !Double.isInfinite(d); }","tryCatchPattern":"try { return DecimalType.instance.add(l, r); } catch (NumberFormatException e) { if (e.getMessage().contains(\"NaN\")) { /* handle non-finite operand */ } throw e; }","preventionTips":["Check isFinite on operands before decimal math","Avoid mixing double results with decimal operations","Fix NaN-producing computations upstream (0.0/0.0 guards)"],"tags":["decimal","arithmetic","nan"],"backgroundTag":"invalid-number-format","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}