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

Thrown (QueryArgumentException) by setParameterValues(Object[] values, QueryParameterBinding<P> binding), reached via setParameterList(String name, Object[] values): when the binding already knows its type (getBindType() != null) and QueryArguments.areInstances(parameterType, values, nodeBuilder) finds the array elements are not instances of that type, the bind is rejected before setBindValues. The exception carries the expected Java type, the array's component type, and the offending array.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java:1415

			@Nonnull Collection<? extends P> values,
			@Nonnull Type<P> type) {
		locateBinding( name ).setBindValues( values, (BindableType<P>) type );
		return this;
	}

	@Override
	@Nonnull
	public CommonQueryContractImplementor setParameterList(@Nonnull String name, @Nonnull Object[] values) {
		final var binding = getQueryParameterBindings().getBinding( name );
		setParameterValues( values, binding );
		return this;
	}

	private <P> void setParameterValues(Object[] values, QueryParameterBinding<P> binding) {
		final var parameterType = binding.getBindType();
		if ( parameterType != null
			&& !areInstances( parameterType, values, getNodeBuilder() ) ) {
			throw new QueryArgumentException( "Argument to query parameter has an incompatible type",
					parameterType.getJavaType(), values.getClass().getComponentType(), values );
		}
		@SuppressWarnings("unchecked") // safe, just checked
		final var castArray = (P[]) values;
		binding.setBindValues( List.of( castArray ) );
	}

	@Override
	@Nonnull
	public <P> CommonQueryContractImplementor setParameterList(
			@Nonnull String name,
			@Nonnull P[] values,
			@Nonnull Class<P> javaType) {
		final var javaDescriptor = getJavaType( javaType );
		if ( javaDescriptor == null ) {
			setParameterList( name, values );
		}
		else {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Convert the array to the parameter's exact component type first: Arrays.stream(strIds).map(Long::valueOf).toArray(Long[]::new)
  2. Check the expected type via the parameter metadata and write the converter against it rather than hardcoding
  3. For string-prone inputs, prefer setParameterList(name, List<Long>) after explicit conversion, or TypedParameterValue-free typed binds via setParameter(name, v, Long.class)

Example fix

// before
query.setParameterList( "ids", new String[]{ "1", "2" } ); // String[] into Long :ids

// after
Long[] ids = Arrays.stream( new String[]{ "1", "2" } ).map( Long::valueOf ).toArray( Long[]::new );
query.setParameterList( "ids", ids );
Defensive patterns

Strategy: validation

Validate before calling

Class<?> expected = query.getParameterMetadata().getQueryParameter( name ).getParameterType();
if ( !expected.isAssignableFrom( values.getClass().getComponentType() ) ) {
    values = convert( values, expected ); // e.g. String[] -> Long[]
}
query.setParameterList( name, values );

Type guard

static <T> boolean arrayMatchesParam(Class<T> expected, Object[] arr) {
    return expected.isAssignableFrom( arr.getClass().getComponentType() );
}

Try / catch

try {
    query.setParameterList( name, values );
} catch ( org.hibernate.query.QueryArgumentException e ) {
    throw new IllegalArgumentException( "IN parameter '" + name + "' needs "
            + e.getExpectedType() + ", got " + (values == null ? "null" : values.getClass().getComponentType()), e );
}

Prevention

When it happens

Trigger: setParameterList("ids", new String[]{"1","2"}) where :ids was inferred as Long from 'o.id in :ids'. Passing Integer[] for a Long-typed parameter (Integer is not an instance of Long). Arrays of boxed values deserialized from JSON/web input (often String[]) forwarded straight into the bind.

Common situations: REST query-param lists arriving as String[] and bound without conversion; schema/type drift between entity attribute type and the frontend payload; refactoring entity id type from Integer to Long (or UUID) while callers still send the old array type.

Related errors


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