{"record":{"id":"fba7ba43cb575253","repo":"hibernate/hibernate-orm","slug":"cannot-coerce-double-value-s-as-short-not-a-w","errorCode":null,"errorMessage":"Cannot coerce Double value `%s` as Short : not a whole number","messagePattern":"Cannot coerce Double value `(.+?)` as Short : not a whole number","errorType":"exception","errorClass":"CoercionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java","lineNumber":200,"sourceCode":"\n\t\treturn value.shortValue();\n\t}\n\n\tpublic static Short toShort(Long value) {\n\t\tif ( value > Short.MAX_VALUE ) {\n\t\t\tthrow new CoercionException( \"Cannot coerce Long value `\" + value + \"` as Short : overflow\" );\n\t\t}\n\n\t\tif ( value < Short.MIN_VALUE ) {\n\t\t\tthrow new CoercionException( \"Cannot coerce Long value `\" + value + \"` as Short : underflow\" );\n\t\t}\n\n\t\treturn value.shortValue();\n\t}\n\n\tpublic static Short toShort(Double doubleValue) {\n\t\tif ( ! isWholeNumber( doubleValue ) ) {\n\t\t\tthrow new CoercionException( \"Cannot coerce Double value `\" + doubleValue + \"` as Short : not a whole number\" );\n\t\t}\n\t\treturn toShort( doubleValue.longValue() );\n\t}\n\n\tpublic static Short toShort(Float floatValue) {\n\t\tif ( ! isWholeNumber( floatValue ) ) {\n\t\t\tthrow new CoercionException( \"Cannot coerce Float value `\" + floatValue + \"` as Short : not a whole number\" );\n\t\t}\n\t\treturn toShort( floatValue.longValue() );\n\t}\n\n\tpublic static Short toShort(BigInteger value) {\n\t\treturn coerceWrappingError( value::shortValueExact );\n\t}\n\n\tpublic static Short toShort(BigDecimal value) {\n\t\treturn coerceWrappingError( value::shortValueExact );\n\t}","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java#L182-L218","documentation":"Hibernate throws this CoercionException when a Double with a fractional part must be coerced to Short. CoercionHelper.toShort(Double) first rejects non-whole values via isWholeNumber before delegating to the Long-based narrowing path. It is reached from ShortJavaType.coerce when a Double value is assigned to or bound against a Short-mapped attribute. Hibernate refuses lossy fractional-to-integral conversion instead of truncating toward zero.","triggerScenarios":"`ShortJavaType.coerce(2.5)` — e.g. `entity.setDiscount(12.75)` on a Short/short attribute, `setParameter(\"s\", 99.9)` against a Short-typed path, or HQL arithmetic like `avg(...)` or `/` producing Double results piped into a SMALLINT-mapped field.","commonSituations":"Percentage/discount values computed as Double but stored in SMALLINT columns; Jackson-deserialized decimal JSON numbers landing on Short DTO fields; report aggregations (averages) written back into integral columns; refactor from Double to Short attribute while producers still emit fractions.","solutions":["Round explicitly if truncation semantics are agreed: `toShort(Math.round(d))` / `(short) Math.round(d)`; otherwise re-type the attribute as Double/BigDecimal.","Change the column to a decimal type (DECIMAL/DOUBLE) if fractional values must be stored.","Validate whole-number-ness at the boundary before persisting or binding.","Fix HQL/Criteria expressions feeding Short paths: apply round()/floor() in the query or compute in Java before assignment."],"exampleFix":"// before\nDouble avgOrder = orders.stream().mapToDouble(o -> o.total).average().orElse(0);\ncustomer.setAvgOrder(avgOrder);     // Short field -> \"not a whole number\"\n\n// after\ncustomer.setAvgOrder((short) Math.round(avgOrder));\n// or declare avgOrder as Double with a DOUBLE column","handlingStrategy":"validation","validationCode":"Double d = computed;\nif (d != Math.rint(d)) throw new IllegalArgumentException(\"must be whole: \" + d);\nentity.setCode(d.longValue() == (long) d.doubleValue() ? (short) d.longValue() : null); // plus range check","typeGuard":"static boolean isWholeNumber(Double d) { return d != null && d == Math.rint(d) && !d.isNaN(); }","tryCatchPattern":"catch CoercionException and translate into an explicit rounding policy decision; do not blanket-catch and drop values.","preventionTips":["Pick one place to round aggregates (avg/sum division) before storing into SMALLINT.","Prefer storing raw averages in DOUBLE and deriving integral views in queries.","Watch HQL integer division: use `cast(... as int)` or round() when feeding Short paths."],"tags":["hibernate","type-coercion","short","double","fractional"],"backgroundTag":"fractional-to-integer-coercion","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}