{"record":{"id":"1a7c29048dded487","repo":"hibernate/hibernate-orm","slug":"null-value-not-allowed-for-multi-valued-parameter","errorCode":null,"errorMessage":"Null value not allowed for multi-valued parameter ':{name}'","messagePattern":"Null value not allowed for multi-valued parameter ':(.+?)'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java","lineNumber":1070,"sourceCode":"\t\treturn getTypeConfiguration().getBasicTypeForJavaType( valueClass ) != null;\n\t}\n\n\tprotected <P> QueryParameterImplementor<P> getQueryParameter(QueryParameterImplementor<P> parameter) {\n\t\treturn parameter;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic CommonQueryContractImplementor setParameter(@Nonnull String name, @Nullable Object value) {\n\t\tsession.checkOpen( false );\n\t\tif ( value instanceof TypedParameterValue<?> typedParameterValue ) {\n\t\t\tsetTypedParameter( name, typedParameterValue );\n\t\t}\n\t\telse {\n\t\t\tfinal var binding = getQueryParameterBindings().getBinding( name );\n\t\t\tif ( multipleBinding( binding.getQueryParameter(), value ) ) {\n\t\t\t\tif ( value == null ) {\n\t\t\t\t\tthrow new IllegalArgumentException( \"Null value not allowed for multi-valued parameter ':\" + name + \"'\" );\n\t\t\t\t}\n\t\t\t\tsetParameterList( name, (Collection<?>) value );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbinding.setBindValue( value, resolveJdbcParameterTypeIfNecessary() );\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <P> CommonQueryContractImplementor setParameter(\n\t\t\t@Nonnull String name,\n\t\t\t@Nullable P value,\n\t\t\t@Nonnull Class<P> javaType) {\n\t\tfinal var javaDescriptor = getJavaType( javaType );\n\t\tif ( javaDescriptor == null ) {","sourceCodeStart":1052,"sourceCodeEnd":1088,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java#L1052-L1088","documentation":"Intended guard in setParameter(String name, Object value): when the parameter allows multi-valued binding (IN-expansion) and multipleBinding(...) is true, a null value is rejected with IllegalArgumentException before attempting setParameterList(name, (Collection) value), because a null cannot be cast to Collection nor expanded. Caveat grounded in the source: multipleBinding() at line 1031 requires value instanceof Collection, so a literal null makes it return false and currently flows into the single-value binding path — this branch is effectively defensive/dead in this exact version but represents the rule 'null is not a valid value for a multi-valued parameter'.","triggerScenarios":"The guarded scenario: query.setParameter(\"ids\", null) where the query contains 'o.id in :ids' and the parameter allows multi-valued binding. Also any subclass/override that widens multipleBinding to treat null as multi-valued will surface this message directly.","commonSituations":"Optional IN filters in dynamic search screens: when no checkboxes are selected, null is passed instead of an empty collection; Optional.map(...).orElse(null) pipelines feeding setParameter.","solutions":["Never pass null for an IN-list parameter — pass List.of() or restructure the query","When the list is optional, build the query dynamically (Criteria API or two HQL variants) so the IN clause is omitted entirely rather than bound to null","Use setParameterList(name, emptyList) semantics via an empty collection when the predicate is absent"],"exampleFix":"// before\nList<Long> ids = filter == null ? null : filter.getIds();\nquery.setParameter( \"ids\", ids ); // null for multi-valued :ids\n\n// after\nList<Long> ids = filter == null ? List.of() : filter.getIds();\nquery.setParameterList( \"ids\", ids );","handlingStrategy":"validation","validationCode":"if ( \"ids\".equals( name ) ) {\n    Collection<?> safe = value == null ? List.of() : ( (Collection<?>) value );\n    query.setParameterList( name, safe );\n} else {\n    query.setParameter( name, value );\n}","typeGuard":"static boolean isMultiValuedParam(org.hibernate.query.Query<?> q, String name) {\n    return q.getParameterMetadata().getQueryParameter( name ).allowsMultiValuedBinding();\n}","tryCatchPattern":null,"preventionTips":["Use List.of() for absent IN filters, never null","Route IN parameters through setParameterList exclusively","When a filter is optional, omit the IN predicate dynamically instead of null-binding"],"tags":["hibernate","query-parameters","null-safety","in-clause","parameter-binding"],"backgroundTag":"null-parameter-value","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}