hibernate/hibernate-orm · error · CoercionException
Cannot coerce Double value `%s` to Byte : not a whole number
Error message
Cannot coerce Double value `%s` to Byte : not a whole number
What it means
Hibernate throws this CoercionException when a Double must be coerced to Byte but has a fractional part. CoercionHelper.toByte(Double) first checks isWholeNumber(value); any value like 3.14 fails before the range checks run. It is reached through ByteJavaType.coerce when a Double value is assigned to or bound against a Byte-mapped attribute. Hibernate treats fractional-to-integral coercion as lossy and rejects it rather than truncating.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java:96
);
}
if ( value < Byte.MIN_VALUE ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Cannot coerce Long value `%s` to Byte : underflow",
value
)
);
}
return value.byteValue();
}
public static Byte toByte(Double value) {
if ( ! isWholeNumber( value ) ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Cannot coerce Double value `%s` to Byte : not a whole number",
value
)
);
}
if ( value > Byte.MAX_VALUE ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Cannot coerce Double value `%s` to Byte : overflow",
value
)
);
}
View on GitHub (pinned to fad1729dce)
Solutions
- Fix the producer: round/quantize before assignment (`(byte) Math.round(d)`) only if truncation semantics are acceptable, otherwise store the value in a Double/BigDecimal-typed column.
- Change the attribute type to Double/BigDecimal if fractional values are legitimate.
- Sanitize incoming data at the boundary: reject or round non-whole numbers before they reach the entity.
- Re-check any HQL/Criteria expressions feeding Byte paths; cast or round in the query (`floor()`, `round()`) as appropriate.
Example fix
// before double avg = readings.stream().mapToDouble(r -> r.value).average().orElse(0); sensor.setCalibration(avg); // Byte field -> "not a whole number" // after sensor.setCalibration((byte) Math.round(avg)); // or make calibration a Double column if fractions matter
Defensive patterns
Strategy: validation
Validate before calling
Double d = computed;
if (d != Math.rint(d) || Double.isNaN(d) || Double.isInfinite(d)) {
throw new IllegalArgumentException("value must be a whole number: " + d);
}
entity.setByteField((byte) (long) (double) d); // after additional range check Type guard
static boolean isWhole(Double d) { return d != null && !d.isNaN() && !d.isInfinite() && d == Math.rint(d); } Try / catch
try { session.persist(e); } catch (CoercionException ex) { /* convert to domain validation error, surface to caller */ } Prevention
- Decide explicitly: either the column stores fractions (use Double/BigDecimal mapping) or the producer must quantize before writing.
- Round in one canonical place (service layer), not ad hoc at call sites.
- Reject NaN/Infinity early — they also fail whole-number checks downstream.
- Cover fractional inputs in contract tests for integral endpoints.
When it happens
Trigger: `ByteJavaType.coerce(3.14)` — e.g. `entity.setRatio(computedDouble)` on a Byte/byte attribute, or `setParameter("b", 2.5)` against a Byte-typed path, or HQL/Criteria arithmetic (averages, division) producing Double results compared/assigned to a Byte attribute.
Common situations: Computed metrics (averages, percentages) stored into tinyint-mapped Byte fields; JSON numbers with decimals (Jackson deserializes as Double) copied onto Byte properties; unit bugs (storing 0.5 kg in a field meant for whole grams); switching an attribute from Double to Byte during a model refactor while old writers still send fractions.
Related errors
- Cannot coerce Double value `%s` to Byte : overflow
- Cannot coerce Double value `%s` to Byte : underflow
- 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 Double value `%s` to Integer: not a whole n
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/cadb2abcc371c4cb.
Report an issue: GitHub.