hibernate/hibernate-orm · error · CoercionException

Cannot coerce Float value `%s` as Short : not a whole number

Error message

Cannot coerce Float value `%s` as Short : not a whole number

What it means

Hibernate throws this CoercionException when a Float with a fractional part is coerced to Short. CoercionHelper.toShort(Float) checks isWholeNumber(floatValue) and fails on values like 1.5f. It is called from ShortJavaType.coerce when a Float value reaches a Short-mapped attribute during ORM operations (persist, merge, query parameter binding). This is Hibernate's fail-fast guard against silent lossy fractional-to-integral conversion.

Source

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

		}

		if ( value < Short.MIN_VALUE ) {
			throw new CoercionException( "Cannot coerce Long value `" + value + "` as Short : underflow" );
		}

		return value.shortValue();
	}

	public static Short toShort(Double doubleValue) {
		if ( ! isWholeNumber( doubleValue ) ) {
			throw new CoercionException( "Cannot coerce Double value `" + doubleValue + "` as Short : not a whole number" );
		}
		return toShort( doubleValue.longValue() );
	}

	public static Short toShort(Float floatValue) {
		if ( ! isWholeNumber( floatValue ) ) {
			throw new CoercionException( "Cannot coerce Float value `" + floatValue + "` as Short : not a whole number" );
		}
		return toShort( floatValue.longValue() );
	}

	public static Short toShort(BigInteger value) {
		return coerceWrappingError( value::shortValueExact );
	}

	public static Short toShort(BigDecimal value) {
		return coerceWrappingError( value::shortValueExact );
	}

	public static Integer toInteger(Byte value) {
		return value.intValue();
	}

	public static Integer toInteger(Short value) {
		return value.intValue();

View on GitHub (pinned to fad1729dce)

Solutions

  1. Round and narrow deliberately: `(short) Math.round(f)` when fractional precision is disposable; else re-type the attribute to Float/BigDecimal.
  2. Store fractional data in a decimal-capable column instead of SMALLINT.
  3. Validate that incoming Numbers are whole before assigning to integral fields.
  4. Where narrowing policy is fixed, encode it once in an AttributeConverter<Float,Short>.

Example fix

// before
Float rating = reviewWidget.getStars();  // e.g. 4.5f
product.setRating(rating);               // Short 'rating' -> "not a whole number"

// after
product.setRating((short) Math.round(rating));
// or map rating as Float with a REAL/FLOAT column
Defensive patterns

Strategy: validation

Validate before calling

Float f = widget.getStars();
if (f != Math.rint(f)) throw new IllegalArgumentException("stars must be whole: " + f);
product.setRating((short) Math.round(f));

Type guard

static boolean isWhole(Float f) { return f != null && !f.isNaN() && f == Math.rint(f); }

Try / catch

catch CoercionException at service boundary -> 400 with field name; deterministic failure, no retry.

Prevention

When it happens

Trigger: Assigning a Float such as 7.3f to a Short/short entity property: `product.setRating(uiRating)` where rating maps to SMALLINT, or `setParameter("s", 4.5f)` against a Short-typed path; common with UI layers and math APIs that return Float.

Common situations: Float-based rating/progress/scale values from mobile or desktop UIs stored in SMALLINT fields; float math libraries feeding integral columns; API DTOs typed Float copied onto Short entities; legacy attribute conversions from Float to Short.

Related errors


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