{"record":{"id":"7ad312a603d2a10d","repo":"hibernate/hibernate-orm","slug":"illegal-attempt-to-bind-a-collection-value-to-a-si","errorCode":null,"errorMessage":"Illegal attempt to bind a collection value to a single-valued parameter","messagePattern":"Illegal attempt to bind a collection value to a single-valued parameter","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java","lineNumber":266,"sourceCode":"\t\tvalues.forEach( this::validate );\n\t\tclarifyType( values, clarifiedType );\n\t\tbindMultipleValues( values );\n\t}\n\n\tprivate void bindMultipleValues(Collection<?> coerced) {\n\t\tfinal List<T> list = new ArrayList<>();\n\t\tfor ( var value : coerced ) {\n\t\t\tlist.add( cast( value ) );\n\t\t}\n\t\tbindValues = list;\n\t\tbindValue = null;\n\t\tisMultiValued = true;\n\t\tisBound = true;\n\t}\n\n\tprivate void assertMultivalued() {\n\t\tif ( !queryParameter.allowsMultiValuedBinding() ) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Illegal attempt to bind a collection value to a single-valued parameter\"\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate void setExplicitTemporalPrecision(@SuppressWarnings(\"deprecation\") TemporalType precision) {\n\t\texplicitTemporalPrecision = precision;\n\t\tif ( bindType == null || isTemporal( determineJavaType( bindType ) ) ) {\n\t\t\tbindType = resolveTemporalPrecision( precision, bindType, getCriteriaBuilder() );\n\t\t}\n\t}\n\n\tprivate JavaType<T> determineJavaType(BindableType<T> bindType) {\n\t\treturn getCriteriaBuilder().resolveExpressible( bindType ).getExpressibleJavaType();\n\t}\n\n\t@Override\n\tpublic @Nullable MappingModelExpressible<T> getType() {","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingImpl.java#L248-L284","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar q = session.createQuery(\n    \"from Person p where p.team.id = :teamIds\", Person.class);\nq.setParameterList(\"teamIds\", teamIds); // throws: '=' position is single-valued\n\n// after\nvar q = session.createQuery(\n    \"from Person p where p.team.id in :teamIds\", Person.class);\nq.setParameterList(\"teamIds\", teamIds);","handlingStrategy":"validation","validationCode":"static void bind(org.hibernate.query.Query<?> q, String name, Object value) {\n    var p = q.getParameterMetadata().getQueryParameter(name);\n    if (value instanceof java.util.Collection<?> c && !p.allowsMultiValuedBinding())\n        throw new IllegalArgumentException(\"Parameter :\" + name\n            + \" is single-valued; bind one element or rewrite the predicate with 'in'\");\n    q.setParameter(name, value);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["hibernate","parameter-binding","collection-parameter","in-clause","illegal-argument"],"backgroundTag":"collection-parameter-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}