{"record":{"id":"1bf493c08950cc81","repo":"hibernate/hibernate-orm","slug":"not-enough-root-entities","errorCode":null,"errorMessage":"Not enough root entities","messagePattern":"Not enough root entities","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/select/AbstractSqmSelectQuery.java","lineNumber":274,"sourceCode":"\t\treturn new HashSet<>( getQuerySpec().getRoots() );\n\t}\n\n\t/**\n\t * @see org.hibernate.query.criteria.JpaCriteriaQuery#getRootList()\n\t */\n\t@Nonnull\n\tpublic List<Root<?>> getRootList() {\n\t\treturn new ArrayList<>( getQuerySpec().getRootList() );\n\t}\n\n\t/**\n\t * @see org.hibernate.query.criteria.JpaCriteriaQuery#getRoot(int, Class)\n\t */\n\t@Nonnull\n\tpublic <E> JpaRoot<? extends E> getRoot(int position, Class<E> type) {\n\t\tfinal var rootList = getQuerySpec().getRootList();\n\t\tif ( rootList.size() <= position ) {\n\t\t\tthrow new IllegalArgumentException( \"Not enough root entities\" );\n\t\t}\n\t\treturn castRoot( rootList.get( position ), type );\n\t}\n\n\t/**\n\t * @see org.hibernate.query.criteria.JpaCriteriaQuery#getRoot(String, Class)\n\t */\n\t@Nonnull\n\tpublic <E> JpaRoot<? extends E> getRoot(String alias, Class<E> type) {\n\t\tfor ( var root : getQuerySpec().getRootList() ) {\n\t\t\tfinal String rootAlias = root.getAlias();\n\t\t\tif ( rootAlias != null && rootAlias.equals( alias ) ) {\n\t\t\t\treturn castRoot( root, type );\n\t\t\t}\n\t\t}\n\t\tthrow new IllegalArgumentException( \"No root entity with alias \" + alias );\n\t}\n","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/select/AbstractSqmSelectQuery.java#L256-L292","documentation":"AbstractSqmSelectQuery.getRoot(int position, Class type) throws IllegalArgumentException when the requested position is >= the number of roots in the query spec — i.e. the query has fewer FROM entities than the index you asked for. Hibernate's criteria API supports multiple roots (cross join style `from A a, B b`), and getRoot(position, ...) is positional access into that root list; calling it with position 1 when only one root exists, or position 2 when two exist, fails here before the castRoot type check even runs.","triggerScenarios":"Code attempts to resolve a single root from a select query that has zero roots registered in its query spec.","commonSituations":"Forgetting to call CriteriaQuery.from() before building selections or predicates that need a root.","solutions":["Use `query.getRootList().size()` (or getRoots()) to bound the position before calling getRoot(position, type)","Prefer alias-based lookup `query.getRoot(\"b\", B.class)` or keep references to the Root objects returned by from()","When roots are conditional, store the from() results in variables/map instead of relying on positional indexes","Add roots first, then resolve positions, in that order"],"exampleFix":"// before\nJpaCriteriaQuery<Tuple> q = cb.createTupleQuery();\nq.from( Person.class );\nJpaRoot<? extends Address> a = q.getRoot( 1, Address.class ); // IllegalArgumentException\n\n// after\nq.from( Address.class );\nJpaRoot<? extends Address> a = q.getRoot( 1, Address.class );","handlingStrategy":"validation","validationCode":"int roots = query.getRootList().size();\nif (position >= roots) {\n    throw new IllegalArgumentException(\"Only \" + roots + \" root(s); position \" + position + \" invalid\");\n}\nJpaRoot<? extends E> r = query.getRoot(position, type);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Hold the Root objects returned by from() instead of re-resolving by position","Bound positional access with getRootList().size()","Prefer alias-based getRoot(alias, type) for multi-root queries"],"tags":["hibernate","criteria-api","multi-root","index-out-of-range","validation"],"backgroundTag":"criteria-api-misuse","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}