hibernate/hibernate-orm · error · CoercionException
Cannot coerce Long value `%s` to Byte : underflow
Error message
Cannot coerce Long value `%s` to Byte : underflow
What it means
Hibernate throws this CoercionException when a Long value being narrowed to Byte falls below -128. Thrown from CoercionHelper.toByte(Long) via ByteJavaType.coerce during persist/update/merge or parameter binding on a Byte-mapped attribute. It is the underflow twin of the overflow check directly above it in the same method; the message carries the offending value. The intent is fail-fast rejection of lossy narrowing conversions in Hibernate 6.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java:82
);
}
return value.byteValue();
}
public static Byte toByte(Long value) {
if ( value > Byte.MAX_VALUE ) {
throw new CoercionException(
String.format(
Locale.ROOT,
"Cannot coerce Long value `%s` to Byte : overflow",
value
)
);
}
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",
valueView on GitHub (pinned to fad1729dce)
Solutions
- Change the attribute or the producing code so types match: declare the field Long/Integer, or convert the long to byte explicitly after a -128..127 check.
- Stop using out-of-range sentinels; store -1 style codes in a properly sized column (SMALLINT/INT) instead of TINYINT/Byte.
- Add an AttributeConverter if deliberate narrowing is required, encoding the policy in one place.
- Guard at the boundary: validate that any Number destined for a Byte field is within byte range before calling Session APIs.
Example fix
// before
long errorCode = computeCode(); // e.g. -500
meter.setCode(errorCode); // Byte 'code' property -> CoercionException: underflow
// after
if (errorCode < Byte.MIN_VALUE || errorCode > Byte.MAX_VALUE) {
throw new IllegalArgumentException("code out of byte range: " + errorCode);
}
meter.setCode((byte) errorCode); Defensive patterns
Strategy: validation
Validate before calling
if (longValue < Byte.MIN_VALUE || longValue > Byte.MAX_VALUE) {
throw new IllegalArgumentException("code out of byte range: " + longValue);
}
entity.setCode((byte) longValue); Type guard
static boolean fitsInByte(long v) { return v >= -128L && v <= 127L; } Try / catch
catch (CoercionException e) when persisting: map to a 422/400 response naming the field; never retry — the failure is deterministic.
Prevention
- Avoid negative sentinel longs for byte-sized status fields.
- Keep unit tests covering negative boundary values (-128/-129).
- Run a data audit when narrowing any column type before switching the attribute.
When it happens
Trigger: `ByteJavaType.coerce(value)` invoked with a Long < -128: assigning a negative Long to a byte/Byte entity field through a loosely typed setter, merging a detached entity whose Byte property was populated from a Long variable, or binding a long literal below -128 to a Byte-typed query parameter.
Common situations: Negative sentinel values (-1L, -999L) used as status/flag codes pushed into tinyint-mapped Byte fields; arithmetic on longs (timestamps deltas, hash codes) feeding a Byte field; data-migration jobs reading wide numeric columns into Byte attributes; upgrade to Hibernate 6 exposing previously silent truncation.
Related errors
- Cannot coerce Integer value `%s` to Byte : underflow
- Cannot coerce Long value `%s` to Byte : overflow
- Cannot coerce Double value `%s` to Byte : underflow
- Cannot coerce Float value `%s` to Byte : underflow
- Cannot coerce Integer value `%s` as Short : underflow
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/cf1dd8ffad5cf623.
Report an issue: GitHub.