hibernate/hibernate-orm · error · QueryArgumentException

Argument to query parameter has an incompatible type: {}

Error message

Argument to query parameter has an incompatible type: {}

What it means

When a bound value must be converted to the parameter's bind type, QueryParameterBindingImpl.coerce applies the JavaType coercion; if that fails (a HibernateException, e.g. 'abc' to Integer), it is rethrown as QueryArgumentException with the parameter type and the offending value. It fires at binding time, so the stack trace points at the setParameter call, not at execution.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java:399

	private void validate(Object value) {
		QueryParameterBindingValidator.validate( queryParameter, bindType, value, sessionFactory );
	}

	private Object coerce(Object value) {
		try {
			if ( bindType != null ) {
				return coerce( value, bindType );
			}
//			else if ( queryParameter.getHibernateType() != null ) {
//				return coerce( value, queryParameter.getHibernateType() );
//			}
			else {
				return value;
			}
		}
		catch (HibernateException ex) {
			throw new QueryArgumentException( "Argument to query parameter has an incompatible type: " + ex.getMessage(),
					queryParameter.getParameterType(), value );
		}
	}

	private Object coerce(Object value, BindableType<T> parameterType) {
		return value == null ? null
				: getCriteriaBuilder().resolveExpressible( parameterType )
						.getExpressibleJavaType().coerce( value );
	}

	private static <T> @Nullable T firstNonNull(Collection<? extends T> values) {
		final var iterator = values.iterator();
		T value = null;
		while ( value == null && iterator.hasNext() ) {
			value = iterator.next();
		}
		return value;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Convert the input to the parameter's Java type before binding (Integer.parseInt, LocalDate.parse with an explicit formatter).
  2. Bind with an explicit matching BindableType when inference is ambiguous.
  3. Validate and normalize external input at the API boundary so repositories only receive typed values.

Example fix

// before
q.setParameter("age", request.getParameter("age")); // "abc" -> QueryArgumentException

// after
int age = Integer.parseInt(request.getParameter("age")); // validate at boundary
q.setParameter("age", age);
Defensive patterns

Strategy: validation

Validate before calling

static Integer toInt(Object raw) {
    if (raw instanceof Integer i) return i;
    try {
        return Integer.parseInt(String.valueOf(raw));
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("Not an integer: " + raw, e);
    }
}

Try / catch

try {
    q.setParameter("age", raw);
} catch (org.hibernate.QueryArgumentException e) {
    // message contains parameter type and value; reject the request input
}

Prevention

When it happens

Trigger: setParameter("age", "abc") where the parameter resolved to Integer; binding '31.12.2024' to a LocalDate parameter; any raw String from a web form or file forwarded into a typed parameter without conversion.

Common situations: REST controllers handing String request params straight to repositories; locale-specific or unexpected date formats; enum name mismatches; CSV/import pipelines feeding untyped data into queries.

Related errors


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