{"record":{"id":"7530c422f661c1ce","repo":"hibernate/hibernate-orm","slug":"not-a-compound-selection","errorCode":null,"errorMessage":"Not a compound selection","messagePattern":"Not a compound selection","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/jpa/AbstractJpaSelection.java","lineNumber":43,"sourceCode":"\tprotected AbstractJpaSelection(@Nullable SqmBindableType<? super T> sqmExpressible, NodeBuilder criteriaBuilder) {\n\t\tsuper( sqmExpressible, criteriaBuilder );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic JpaSelection<T> alias(@Nonnull String alias) {\n\t\tsetAlias( alias );\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic boolean isCompoundSelection() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic List<? extends JpaSelection<?>> getSelectionItems() {\n\t\tthrow new IllegalStateException( \"Not a compound selection\" );\n\t}\n}\n","sourceCodeStart":25,"sourceCodeEnd":46,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/jpa/AbstractJpaSelection.java#L25-L46","documentation":"AbstractJpaSelection.getSelectionItems throws IllegalStateException when called on a selection that is not a compound selection. In the JPA Criteria API getSelectionItems() is only meaningful for selections built via multiselect()/tuple/array/construct builders that aggregate several items; the base implementation in Hibernate returns isCompoundSelection()==false and treats getSelectionItems() as an illegal call. Subclasses that are compound (e.g. SqmJpaCompoundSelection) override both methods.","triggerScenarios":"Calling `selection.getSelectionItems()` on a plain expression/path (a single SqmPath, literal, parameter, function result); generic result-mapping code that iterates `query.getSelection().getSelectionItems()` for both single and multi selects; transformers that flatten selection trees without checking isCompoundSelection first.","commonSituations":"DTO-projection frameworks that walk the criteria selection tree to derive column aliases/types; code that worked against multiselect queries breaking the first time it receives a single-item selection; migrating hand-rolled HQL result mapping to criteria where the selection is one expression.","solutions":["Guard with `if (selection.isCompoundSelection())` and treat non-compound as a single item","Use `List.of(selection)` for the non-compound branch so downstream code sees a uniform list","For explicit multi-item selections use cb.tuple()/cb.array()/cb.construct(...) or query.multiselect(...) so the compound implementation is used","In tree-walkers, recurse via instanceof checks on SqmExpression subtypes rather than assuming getSelectionItems exists"],"exampleFix":"// before\nList<? extends JpaSelection<?>> items = query.getSelection().getSelectionItems(); // IllegalStateException for single select\n\n// after\nJpaSelection<?> sel = query.getSelection();\nList<? extends JpaSelection<?>> items = sel.isCompoundSelection()\n        ? sel.getSelectionItems()\n        : List.of( sel );","handlingStrategy":"type-guard","validationCode":"if (selection.isCompoundSelection()) {\n    items = selection.getSelectionItems();\n} else {\n    items = List.of(selection);\n}","typeGuard":"static List<? extends jakarta.persistence.criteria.Selection<?>> itemsOf(\n        jakarta.persistence.criteria.Selection<?> s) {\n    return s.isCompoundSelection() ? s.getSelectionItems() : List.of(s);\n}","tryCatchPattern":null,"preventionTips":["Always pair getSelectionItems() with an isCompoundSelection() check","Use multiselect()/tuple()/array() when you need a guaranteed compound selection","Write one itemsOf() utility and use it everywhere in selection-walking code"],"tags":["hibernate","criteria-api","selection","projection","illegal-state"],"backgroundTag":"criteria-api-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}