hibernate/hibernate-orm · error · CoercionException
Cannot coerce Float value `%s` as Short : not a whole number
Error message
Cannot coerce Float value `%s` as Short : not a whole number
What it means
Hibernate throws this CoercionException when a Float with a fractional part is coerced to Short. CoercionHelper.toShort(Float) checks isWholeNumber(floatValue) and fails on values like 1.5f. It is called from ShortJavaType.coerce when a Float value reaches a Short-mapped attribute during ORM operations (persist, merge, query parameter binding). This is Hibernate's fail-fast guard against silent lossy fractional-to-integral conversion.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java:207
}
if ( value < Short.MIN_VALUE ) {
throw new CoercionException( "Cannot coerce Long value `" + value + "` as Short : underflow" );
}
return value.shortValue();
}
public static Short toShort(Double doubleValue) {
if ( ! isWholeNumber( doubleValue ) ) {
throw new CoercionException( "Cannot coerce Double value `" + doubleValue + "` as Short : not a whole number" );
}
return toShort( doubleValue.longValue() );
}
public static Short toShort(Float floatValue) {
if ( ! isWholeNumber( floatValue ) ) {
throw new CoercionException( "Cannot coerce Float value `" + floatValue + "` as Short : not a whole number" );
}
return toShort( floatValue.longValue() );
}
public static Short toShort(BigInteger value) {
return coerceWrappingError( value::shortValueExact );
}
public static Short toShort(BigDecimal value) {
return coerceWrappingError( value::shortValueExact );
}
public static Integer toInteger(Byte value) {
return value.intValue();
}
public static Integer toInteger(Short value) {
return value.intValue();View on GitHub (pinned to fad1729dce)
Solutions
- Round and narrow deliberately: `(short) Math.round(f)` when fractional precision is disposable; else re-type the attribute to Float/BigDecimal.
- Store fractional data in a decimal-capable column instead of SMALLINT.
- Validate that incoming Numbers are whole before assigning to integral fields.
- Where narrowing policy is fixed, encode it once in an AttributeConverter<Float,Short>.
Example fix
// before Float rating = reviewWidget.getStars(); // e.g. 4.5f product.setRating(rating); // Short 'rating' -> "not a whole number" // after product.setRating((short) Math.round(rating)); // or map rating as Float with a REAL/FLOAT column
Defensive patterns
Strategy: validation
Validate before calling
Float f = widget.getStars();
if (f != Math.rint(f)) throw new IllegalArgumentException("stars must be whole: " + f);
product.setRating((short) Math.round(f)); Type guard
static boolean isWhole(Float f) { return f != null && !f.isNaN() && f == Math.rint(f); } Try / catch
catch CoercionException at service boundary -> 400 with field name; deterministic failure, no retry.
Prevention
- Quantize UI float inputs to steps (e.g. half-stars) via int at the boundary, or store ratings as Float.
- Keep rating columns FLOAT/DECIMAL if fractional ratings are a product requirement.
When it happens
Trigger: Assigning a Float such as 7.3f to a Short/short entity property: `product.setRating(uiRating)` where rating maps to SMALLINT, or `setParameter("s", 4.5f)` against a Short-typed path; common with UI layers and math APIs that return Float.
Common situations: Float-based rating/progress/scale values from mobile or desktop UIs stored in SMALLINT fields; float math libraries feeding integral columns; API DTOs typed Float copied onto Short entities; legacy attribute conversions from Float to Short.
Related errors
- Cannot coerce Float value `%s` to Byte : not a whole number
- Cannot coerce Double value `%s` as Short : not a whole numbe
- Unable to coerce Float value `%s` to Integer: not a whole nu
- Unable to coerce Float value `%s` as Integer: not a whole nu
- Cannot coerce Double value `%s` to Byte : not a whole number
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e810be7662a3c641.
Report an issue: GitHub.