hibernate/hibernate-orm · error · FunctionArgumentException

Parameter %d of function '%s()' has type '%s', but argument

Error message

Parameter %d of function '%s()' has type '%s', but argument is of type '%s'

What it means

AvgFunction validates that the single argument of avg() resolves to a JDBC type classified as numeric (integer/decimal/float families). A non-numeric domain type such as String, Boolean, or a UUID produces this FunctionArgumentException naming the offending type, because there is no meaningful AVG over it and the SQL would fail anyway.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java:176

				BindingContext bindingContext) {
			if ( arguments.size() != 1 ) {
				throw new FunctionArgumentException(
						String.format(
								Locale.ROOT,
								"Function %s() has %d parameters, but %d arguments given",
								functionName,
								1,
								arguments.size()
						)
				);
			}
			final var expressible = arguments.get( 0 ).getExpressible();
			if ( expressible != null ) {
				final var domainType = expressible.getSqmType();
				if ( domainType != null ) {
					final var jdbcType = getJdbcType( domainType, bindingContext.getTypeConfiguration() );
					if ( !isNumeric( jdbcType ) ) {
						throw new FunctionArgumentException(
								String.format(
										"Parameter %d of function '%s()' has type '%s', but argument is of type '%s'",
										1,
										functionName,
										NUMERIC,
										domainType.getTypeName()
								)
						);
					}
				}
			}
		}

		private static boolean isNumeric(JdbcType jdbcType) {
			final int sqlTypeCode = jdbcType.getDefaultSqlTypeCode();
			return isNumericType( sqlTypeCode )
				|| jdbcType instanceof ArrayJdbcType arrayJdbcType
						&& isNumeric( arrayJdbcType.getElementJdbcType() );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Apply an explicit cast before averaging: 'select avg(cast(e.amount as double)) ...' when the field is stored as a String
  2. Fix the entity mapping so numeric data uses a numeric Java/JDBC type (Integer/BigDecimal/...)
  3. If the value is genuinely non-numeric, remove avg() and use a different aggregate (min/max/count) or string functions

Example fix

// before (amount is String)
Double a = session.createQuery("select avg(e.amount) from Order e", Double.class).getSingleResult();

// after
Double a = session.createQuery("select avg(cast(e.amount as double)) from Order e", Double.class).getSingleResult();
Defensive patterns

Strategy: validation

Validate before calling

// before executing, confirm the path type is numeric if you build queries dynamically
SqmExpressible<?> t = ((SqmExpression<?>) arg).getExpressible();
if (t != null && !t.getSqmType().getTypeName().matches("(int|long|float|double|big_decimal).*")) {
    throw new IllegalArgumentException("avg() needs numeric argument, got " + t);
}

Type guard

boolean isAvgEligible(Class<?> c) {
    return Number.class.isAssignableFrom(c)
        || c == int.class || c == long.class || c == double.class || c == float.class;
}

Try / catch

catch (FunctionArgumentException e) {
    // surface as a user-facing validation error with query context
    throw new QuerySyntaxException("avg() requires a numeric argument", e);
}

Prevention

When it happens

Trigger: Queries like 'select avg(e.name) from Employee e', avg() over a String-mapped numeric stored as varchar, avg() over an enum or boolean field; also avg() over a char/enum mapped with @Enumerated where the SqmType is not numeric.

Common situations: Legacy schemas storing numbers as varchar/String fields and then used in aggregates; enum ordinals averaged by mistake; upgrading from Hibernate 5 where avg() type-checking was laxer and the query silently produced garbage or DB errors.

Related errors


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