hibernate/hibernate-orm · error · IllegalArgumentException
Illegal attempt to bind a collection value to a single-value
Error message
Illegal attempt to bind a collection value to a single-valued parameter
What it means
QueryParameterBindingImpl.assertMultivalued checks queryParameter.allowsMultiValuedBinding() before a collection is expanded into SQL parameter slots. Hibernate marks a parameter single-valued when it is not used in a position that accepts a collection (IN-style predicate), so binding a collection to it throws IllegalArgumentException. The guard fires at binding time, before SQL generation.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java:266
values.forEach( this::validate );
clarifyType( values, clarifiedType );
bindMultipleValues( values );
}
private void bindMultipleValues(Collection<?> coerced) {
final List<T> list = new ArrayList<>();
for ( var value : coerced ) {
list.add( cast( value ) );
}
bindValues = list;
bindValue = null;
isMultiValued = true;
isBound = true;
}
private void assertMultivalued() {
if ( !queryParameter.allowsMultiValuedBinding() ) {
throw new IllegalArgumentException(
"Illegal attempt to bind a collection value to a single-valued parameter"
);
}
}
private void setExplicitTemporalPrecision(@SuppressWarnings("deprecation") TemporalType precision) {
explicitTemporalPrecision = precision;
if ( bindType == null || isTemporal( determineJavaType( bindType ) ) ) {
bindType = resolveTemporalPrecision( precision, bindType, getCriteriaBuilder() );
}
}
private JavaType<T> determineJavaType(BindableType<T> bindType) {
return getCriteriaBuilder().resolveExpressible( bindType ).getExpressibleJavaType();
}
@Override
public @Nullable MappingModelExpressible<T> getType() {View on GitHub (pinned to fad1729dce)
Solutions
- Rewrite the predicate so the parameter is collection-valued: 'where x.id in :ids' (Hibernate 6 needs no parentheses).
- Or bind a single element with plain setParameter if the query really is single-valued.
- If both shapes are needed, build the query dynamically and choose '=' or 'in' together with the matching bind call.
Example fix
// before
var q = session.createQuery(
"from Person p where p.team.id = :teamIds", Person.class);
q.setParameterList("teamIds", teamIds); // throws: '=' position is single-valued
// after
var q = session.createQuery(
"from Person p where p.team.id in :teamIds", Person.class);
q.setParameterList("teamIds", teamIds); Defensive patterns
Strategy: validation
Validate before calling
static void bind(org.hibernate.query.Query<?> q, String name, Object value) {
var p = q.getParameterMetadata().getQueryParameter(name);
if (value instanceof java.util.Collection<?> c && !p.allowsMultiValuedBinding())
throw new IllegalArgumentException("Parameter :" + name
+ " is single-valued; bind one element or rewrite the predicate with 'in'");
q.setParameter(name, value);
} Prevention
- When a filter becomes multi-valued, change '=' to 'in' in the same commit.
- Do not blanket-bind collections from generic filter maps.
- Keep each filter's predicate template and bind style next to each other.
When it happens
Trigger: setParameterList("ids", list) or setParameter("ids", collection) when :ids appears in a single-valued position, e.g. 'where x.id = :ids', a select expression, or an arithmetic/concat operand. Criteria parameters not used in an IN predicate are likewise single-valued.
Common situations: Changing 'x.id = :id' to accept a list of ids and forgetting to change '=' to 'in'; generic filter frameworks that always bind collections regardless of the predicate; refactoring a single value into a list without touching the HQL.
Related errors
- Null value not allowed for multi-valued parameter ':{name}'
- Could not resolve jakarta.persistence.Parameter '{}' to org.
- Could not resolve NativeQuery parameter type : `%s`
- Informix only supports the case insensitive flag 'i' as lite
- Unable to locate JdbcValueDescriptor for column `%s`
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7ad312a603d2a10d.
Report an issue: GitHub.