{"record":{"id":"c5c18b533af9581b","repo":"hibernate/hibernate-orm","slug":"empty-selections-passed-to-criteria-query-typed-as-c5c18b","errorCode":null,"errorMessage":"empty selections passed to criteria query typed as Object","messagePattern":"empty selections passed to criteria query typed as Object","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/select/SqmSubQuery.java","lineNumber":295,"sourceCode":"\tpublic SqmSubQuery<T> multiselect(Selection<?>... selections) {\n\t\tvalidateComplianceMultiselect();\n\t\tfinal Selection<? extends T> resultSelection = getResultSelection( selections );\n\t\tgetQuerySpec().setSelection( (JpaSelection<T>) resultSelection );\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic SqmSubQuery<T> multiselect(List<Selection<?>> selectionList) {\n\t\tvalidateComplianceMultiselect();\n\t\tgetQuerySpec().setSelection( getResultSelection( selectionList ) );\n\t\treturn this;\n\t}\n\n\tprivate JpaSelection<T> getResultSelection(List<Selection<?>> selections) {\n\t\tfinal Class<T> resultType = getResultType();\n\t\tif ( resultType == Object.class ) {\n\t\t\tfinal JpaSelection<?> selection = switch ( selections.size() ) {\n\t\t\t\tcase 0 -> throw new IllegalArgumentException(\n\t\t\t\t\t\t\"empty selections passed to criteria query typed as Object\" );\n\t\t\t\tcase 1 -> (JpaSelection<?>) selections.get( 0 );\n\t\t\t\tdefault -> nodeBuilder().array( selections );\n\t\t\t};\n\t\t\t//noinspection unchecked\n\t\t\treturn (JpaSelection<T>) selection;\n\t\t}\n\t\telse if ( Tuple.class.isAssignableFrom( resultType ) ) {\n\t\t\t//noinspection unchecked\n\t\t\treturn (JpaSelection<T>) nodeBuilder().tuple( selections );\n\t\t}\n\t\telse if ( resultType.isArray() ) {\n\t\t\treturn nodeBuilder().array( resultType, selections );\n\t\t}\n\t\telse {\n\t\t\treturn nodeBuilder().construct( resultType, selections );\n\t\t}\n\t}","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/select/SqmSubQuery.java#L277-L313","documentation":"When a criteria (sub)query has result type Object, SqmSubQuery.getResultSelection decides the selection purely from the size of the list passed to multiselect(List): one item becomes that item, several become an array. With zero selections there is nothing to render in the SELECT clause, so Hibernate throws IllegalArgumentException rather than generating invalid SQL. In practice this means multiselect was called with an empty list, or select() was never invoked before execution.","triggerScenarios":"query.subquery(Object.class) followed by subquery.multiselect(Collections.emptyList()) or List.of(); dynamic query builders that always call multiselect() and pass a computed list that ends up empty; refactors that drop the select() call.","commonSituations":"Dynamic-filter APIs where the selection list is assembled from user input or conditionals and can legitimately be empty; generic projection frameworks that wrap every criteria in multiselect without checking.","solutions":["Ensure the subquery gets exactly one selection before execution: call subquery.select(expression) instead of multiselect when a single value is expected","Guard dynamic builders: if the selection list is empty, throw your own descriptive exception or skip executing the query","Give the subquery a concrete result type (Long, String, Tuple) so mistakes surface earlier"],"exampleFix":"// before\nList<Selection<?>> empty = List.of();\nsub.multiselect(empty); // IllegalArgumentException at getResultSelection\n\n// after\nif (selections.isEmpty()) {\n    throw new IllegalStateException(\"Subquery requires at least one selection\");\n}\nsub.multiselect(selections);","handlingStrategy":"validation","validationCode":"if (selections == null || selections.isEmpty()) {\n    throw new IllegalStateException(\"Refusing to build subquery with empty selection\");\n}\nsub.multiselect(selections);","typeGuard":null,"tryCatchPattern":"try { sub.multiselect(list); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"empty selections\")) { /* log and skip query or default to select(cb.literal(1)) */ } else throw e; }","preventionTips":["In dynamic builders, always end with exactly one select()/multiselect() call and assert the list is non-empty","Prefer subquery.select(singleExpression) when the result type is Object","Unit-test dynamic query builders with empty filter inputs"],"tags":["hibernate","criteria-api","multiselect","subquery","validation"],"backgroundTag":"empty-selection-list","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}