hibernate/hibernate-orm · error · CoercionException
Unable to coerce Double Float `%s` as BigInteger: not a whol
Error message
Unable to coerce Double Float `%s` as BigInteger: not a whole number
What it means
Thrown by CoercionHelper.toBigInteger(Float) when Hibernate coerces a Float into a BigInteger basic type and the isWholeNumber(floatValue) check fails, i.e. the value has a fractional part. Hibernate runs this coercion when a BigInteger attribute or query parameter receives a float-typed value. The odd wording 'Double Float' is a copy-paste artifact from the Double overload; the real meaning is simply that the Float is not a whole number.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java:329
return coerceWrappingError( value::longValueExact );
}
public static BigInteger toBigInteger(Double doubleValue) {
if ( ! isWholeNumber( doubleValue ) ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Unable to coerce Double value `%s` as BigInteger: not a whole number",
doubleValue
)
);
}
return BigInteger.valueOf( doubleValue.longValue() );
}
public static BigInteger toBigInteger(Float floatValue) {
if ( ! isWholeNumber( floatValue ) ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Unable to coerce Double Float `%s` as BigInteger: not a whole number",
floatValue
)
);
}
return BigInteger.valueOf( floatValue.longValue() );
}
public static BigInteger toBigInteger(BigDecimal value) {
return coerceWrappingError( value::toBigIntegerExact );
}
public static Double toDouble(Float floatValue) {
if ( floatValue > (float) Double.MAX_VALUE ) {
throw new CoercionException(
String.format(View on GitHub (pinned to fad1729dce)
Solutions
- Round or truncate explicitly before assigning: BigInteger.valueOf(floatValue.longValue()) or Math.round, so the lossy conversion is intentional
- Change the entity attribute type to match the real data (BigDecimal or Double) instead of BigInteger
- Pass the exact target type from the start and remove float-typed intermediaries
- As a boundary guard, catch org.hibernate.type.descriptor.java.CoercionException and reject the input with a validation error
Example fix
// before entity.setAmount(2.5f); // field is BigInteger -> CoercionException: not a whole number // after entity.setAmount(BigInteger.valueOf((long) 2.5f)); // explicit truncation // or better: change the field to BigDecimal and keep the fraction
Defensive patterns
Strategy: validation
Validate before calling
static BigInteger toBigIntegerSafe(Float v) {
if (v == null) return null;
if (!v.isFinite() || v % 1.0f != 0.0f) {
throw new IllegalArgumentException("not a whole number: " + v);
}
return BigInteger.valueOf(v.longValue());
} Type guard
static boolean isWholeFloat(Number n) {
return n instanceof Float f && f.isFinite() && f % 1.0f == 0.0f;
} Try / catch
try {
session.persist(entity);
} catch (CoercionException e) {
// rethrow as a user-facing validation error naming the field
throw new BadRequestException("value must be a whole number", e);
} Prevention
- Keep entity attribute types aligned with the values you actually set
- Never rely on implicit Number coercion for BigInteger fields
- Unit-test setters with the exact runtime types your JSON/deserializer produces
When it happens
Trigger: Binding a fractional float such as setParameter("n", 2.5f) where the path/attribute is BigInteger; assigning a Float that came from JSON, a Map<String,Object>, or a reflective setter to a BigInteger entity field; result coercion when the declared Java type is BigInteger but the incoming value arrives boxed as Float.
Common situations: Loosely typed input (JSON payloads, row maps) mapped onto strict numeric entity fields; refactoring a field from Double/Float to BigInteger without cleaning producers; older service APIs that hand out Float for quantities now stored as integers.
Related errors
- Cannot coerce Float value `%s` to Double : underflow
- Cannot coerce value '%s' [%s] to Float
- Unable to coerce value [%s (%s)] to BigInteger
- Cannot coerce Float value `%s` to Byte : not a whole number
- Cannot coerce Float value `%s` to Byte : overflow
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/72b2ef31f4f66939.
Report an issue: GitHub.