hibernate/hibernate-orm · error · CoercionException
Unable to coerce Float value `%s` as Integer: not a whole nu
Error message
Unable to coerce Float value `%s` as Integer: not a whole number
What it means
Hibernate throws this CoercionException when a Float with a fractional part is coerced to Long. As with its Double sibling, the message text is wrong: CoercionHelper.toLong(Float) says "as Integer" even though the target is Long — a copy-paste artifact in Hibernate, so trust the stack trace (LongJavaType.coerce -> toLong) over the message wording. The isWholeNumber guard fires from LongJavaType.coerce whenever a fractional Float reaches a Long-mapped attribute.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java:295
return value.longValue();
}
public static Long toLong(Double doubleValue) {
if ( ! isWholeNumber( doubleValue ) ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Unable to coerce Double value `%s` as Integer: not a whole number",
doubleValue
)
);
}
return doubleValue.longValue();
}
public static Long toLong(Float floatValue) {
if ( ! isWholeNumber( floatValue ) ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Unable to coerce Float value `%s` as Integer: not a whole number",
floatValue
)
);
}
return floatValue.longValue();
}
public static Long toLong(BigInteger value) {
return coerceWrappingError( value::longValueExact );
}
public static Long toLong(BigDecimal value) {
return coerceWrappingError( value::longValueExact );
}
View on GitHub (pinned to fad1729dce)
Solutions
- Fix the producer to emit integral types, or convert explicitly: verify whole-number then `floatValue()`/`Math.round(f)` before assigning to the Long field.
- Store fractional values in FLOAT/DOUBLE columns rather than BIGINT.
- Validate incoming Numbers for whole-number-ness at the boundary.
- Read the stack trace, not the message: this variant is the Float -> Long case despite the Integer wording.
Example fix
// before Float elapsed = timer.elapsedFraction(); // e.g. 12.9f job.setDuration(elapsed); // Long 'duration' -> CoercionException (message says "as Integer") // after job.setDuration((long) Math.round(elapsed)); // or map duration as Float if sub-second fractions matter
Defensive patterns
Strategy: validation
Validate before calling
Float f = timer.fraction();
if (f != Math.rint(f)) throw new IllegalArgumentException("duration must be whole: " + f);
job.setDuration((long) Math.round(f)); Type guard
static boolean isWholeFloatForLong(Float f) { return f != null && f == Math.rint(f) && !f.isNaN() && !f.isInfinite(); } Try / catch
catch CoercionException; the message says "as Integer" but the target is Long — use the stack trace to classify; map to a validation error.
Prevention
- Produce durations as long milliseconds, not float seconds.
- Keep loosely typed Map payloads out of Long-mapped fields.
- When this appears with "Integer" text, don't chase Integer mappings — check Long attributes.
When it happens
Trigger: `LongJavaType.coerce(2.5f)` — assigning a Float to a Long/long field (counts, durations, ids) through a Number/Object-typed setter or dynamic map, or `setParameter("n", 3.7f)` bound against a Long-typed path.
Common situations: Float-valued durations or scores from UIs/simulations persisted into BIGINT-mapped Long fields; loosely typed Map<String,Object> payloads; developers misled by the "Integer" text in the message while actually debugging a Long mapping; analytics feeds emitting floats for integral counts.
Related errors
- Unable to coerce Double value `%s` as Integer: not a whole n
- Cannot coerce Float value `%s` to Byte : not a whole number
- Cannot coerce Float value `%s` as Short : not a whole number
- Unable to coerce Float value `%s` to 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/d4a919d9580c8fc3.
Report an issue: GitHub.