hibernate/hibernate-orm · error · CoercionException

Cannot coerce Double value `%s` to Byte : underflow

Error message

Cannot coerce Double value `%s` to Byte : underflow

What it means

Hibernate throws this CoercionException when a whole-number Double is narrowed to Byte and is below -128. CoercionHelper.toByte(Double) checks isWholeNumber, then the upper bound, then fails `value < Byte.MIN_VALUE`. It is the Double underflow counterpart reached from ByteJavaType.coerce. The offending value is embedded in the message, and the failure is deterministic — retrying never helps.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CoercionHelper.java:116

							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
					)
			);
		}

		if ( value < Byte.MIN_VALUE ) {
			throw new CoercionException(
					String.format(
							Locale.ROOT,
							"Cannot coerce Double value `%s` to Byte : underflow",
							value
					)
			);
		}

		return value.byteValue();
	}

	public static Byte toByte(Float value) {
		if ( ! isWholeNumber( value ) ) {
			throw new CoercionException(
					String.format(
							Locale.ROOT,
							"Cannot coerce Float value `%s` to Byte : not a whole number",
							value

View on GitHub (pinned to fad1729dce)

Solutions

  1. Match the attribute type to the value domain (Byte -> Double/Integer/Long) or pre-validate and narrow explicitly after a -128..127 check.
  2. Correct the upstream computation that produces out-of-range magnitudes (unit or sign errors).
  3. Reject out-of-range values at the import/API boundary with a clear domain error.
  4. If intentional, encode narrowing in an AttributeConverter instead of relying on implicit coercion.

Example fix

// before
Double delta = oldReading - newReading;  // e.g. -500.0
sensor.setDelta(delta);                  // Byte field -> underflow

// after
long l = Math.round(delta);
if (l < Byte.MIN_VALUE || l > Byte.MAX_VALUE) {
    sensor.setDelta(null);               // or throw a domain exception
} else {
    sensor.setDelta((byte) l);
}
Defensive patterns

Strategy: validation

Validate before calling

long l = Math.round(delta);
if (l < Byte.MIN_VALUE || l > Byte.MAX_VALUE) throw new IllegalArgumentException("delta out of byte range: " + l);
entity.setDelta((byte) l);

Type guard

static boolean fitsInByte(Double d) { return d != null && d == Math.rint(d) && d >= -128.0 && d <= 127.0; }

Try / catch

try { session.merge(e); } catch (CoercionException ex) { log field + value; return validation error; }

Prevention

When it happens

Trigger: Assigning a whole Double < -128 (e.g. -200.0, -1e5) to a Byte/byte entity attribute, or binding it as a parameter to a Byte-typed query path; e.g. `entity.setOffset(-300.0)` where offset is Byte.

Common situations: Negative Double deltas or error scores stored into tinyint Byte fields; financial/scientific computations emitting large-magnitude negative doubles; unit mismatches (milliseconds vs seconds) inflating values past the byte range; upgrading Hibernate and losing silent truncation.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/c5cef95aa669f2e2. Report an issue: GitHub.