hibernate/hibernate-orm · error · CoercionException

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

Error message

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

What it means

Hibernate throws this CoercionException when a whole-number Double must be narrowed to Byte and exceeds 127. CoercionHelper.toByte(Double) passes the isWholeNumber check but then fails `value > Byte.MAX_VALUE` (note: comparing Double to Byte.MAX_VALUE widens the byte constant). Reached via ByteJavaType.coerce for Double values supplied to Byte-mapped attributes. Hibernate 6 rejects the lossy narrowing instead of truncating the double as a Java cast would.

Source

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

			);
		}

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

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

View on GitHub (pinned to fad1729dce)

Solutions

  1. Verify the value domain: if values above 127 are legitimate, widen the attribute/column (Byte -> Integer/Short, TINYINT -> SMALLINT/INT).
  2. If narrowing is intended, validate and convert explicitly: check -128..127 then `(byte) doubleValue`.
  3. Fix upstream producers that emit Double for integral quantities (change DTO field types to Integer).
  4. Add an AttributeConverter<Double,Byte> to centralize an intentional rounding+narrowing policy.

Example fix

// before
Double score = analytics.scoreFor(id);  // e.g. 150.0
player.setSkill(score);                 // Byte 'skill' -> overflow

// after
int i = (int) Math.round(score);
if (i < Byte.MIN_VALUE || i > Byte.MAX_VALUE) throw new IllegalArgumentException("skill too large: " + i);
player.setSkill((byte) i);
Defensive patterns

Strategy: validation

Validate before calling

double d = score;
if (d < Byte.MIN_VALUE || d > Byte.MAX_VALUE) throw new IllegalArgumentException("score out of byte range: " + d);
if (d != Math.rint(d)) throw new IllegalArgumentException("score must be whole: " + d);
entity.setScore((byte) (long) d);

Type guard

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

Try / catch

catch CoercionException around session ops and translate to a user-facing range error; do not retry.

Prevention

When it happens

Trigger: `ByteJavaType.coerce(130.0)` — assigning a whole Double like 130.0 or 1e3 to a Byte/byte entity field, or binding such a value as a query parameter against a Byte-typed path; common when Double-typed counters or scores feed a tinyint-mapped property.

Common situations: Scores/ratings stored as tinyint Byte but computed as Double and exceeding the range; Jackson-deserialized decimals (e.g. "128.0") landing on Byte fields; Excel/CSV imports that render all numbers as doubles; Hibernate 5 -> 6 upgrades where the old version silently truncated.

Related errors


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