{"record":{"id":"656327f02212d4b9","repo":"hibernate/hibernate-orm","slug":"the-jpa-specification-does-not-permit-specifying-a","errorCode":null,"errorMessage":"The JPA specification does not permit specifying an alias for fetch joins.","messagePattern":"The JPA specification does not permit specifying an alias for fetch joins\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/AbstractSqmAttributeJoin.java","lineNumber":102,"sourceCode":"\t\treturn fetchJoin;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic SqmAttributeJoin<L,R> alias(@Nonnull String name) {\n\t\tvalidateFetchAlias( name, fetchJoin, nodeBuilder() );\n\t\treturn (SqmAttributeJoin<L, R>) super.alias( name );\n\t}\n\n\t@Override\n\tpublic void clearFetched() {\n\t\tfetchJoin = false;\n\t}\n\n\tprivate static void validateFetchAlias(@Nullable String alias, boolean fetchJoin, NodeBuilder nodeBuilder) {\n\t\tif ( fetchJoin && alias != null && !alias.startsWith( \"var_\" )\n\t\t\t\t&& nodeBuilder.isJpaQueryComplianceEnabled() ) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"The JPA specification does not permit specifying an alias for fetch joins.\"\n\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic <X> X accept(SemanticQueryWalker<X> walker) {\n\t\treturn walker.visitQualifiedAttributeJoin( this );\n\t}\n\n\n\t// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\t// JPA\n\n\t@Override\n\tpublic @Nonnull PersistentAttribute<? super L, ?> getAttribute() {\n\t\t//noinspection unchecked\n\t\treturn (PersistentAttribute<? super L, ?>) getModel();","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/AbstractSqmAttributeJoin.java#L84-L120","documentation":"AbstractSqmAttributeJoin.alias(String) validates aliases of fetch joins: when the join is a fetch join, an alias is set, it does not start with Hibernate's internal 'var_' prefix, and JPA query compliance (hibernate.jpa.compliance.query) is enabled, it throws IllegalStateException because the JPA specification forbids assigning aliases to fetch joins. With compliance disabled (the default) arbitrary fetch aliases are allowed as a Hibernate extension.","triggerScenarios":"root.fetch(\"items\").alias(\"i\") or fetch(attribute, joinType).alias(name) while the persistence unit sets hibernate.jpa.compliance.query=true; also aliasing a join that was marked fetched via fetch-join reuse.","commonSituations":"Enabling JPA query compliance for certification/portability in a codebase that aliases fetch joins (commonly to order by or to reference a fetched element's attribute); environment differences where one persistence unit sets the flag and another does not, so the code only breaks in the compliant environment.","solutions":["Remove the alias from the fetch join; reference the fetched attribute through the owning root path instead.","If you need to sort/filter on the association, use a real join (root.join(...)) rather than fetch, alias that, and mark the fetch separately if eager fetching is required.","As a Hibernate-specific escape hatch, prefix the alias with 'var_' (the generated-alias prefix is exempt).","Turn off the setting: hibernate.jpa.compliance.query=false."],"exampleFix":"// before (compliance on)\nroot.fetch( \"items\", JoinType.LEFT ).alias( \"i\" );\ncb.desc( root.get( \"items\" ).get( \"createdOn\" ) );\n// after\nroot.fetch( \"items\", JoinType.LEFT );\ncb.desc( root.join( \"items\", JoinType.LEFT ).get( \"createdOn\" ) );","handlingStrategy":"validation","validationCode":"static void aliasSafely(JpaFetch<?, ?> fetch, String alias, NodeBuilder cb) {\n    if ( cb.isJpaQueryComplianceEnabled() ) {\n        return; // skip aliasing under JPA compliance\n    }\n    fetch.alias( alias );\n}","typeGuard":"static boolean aliasAllowedOnFetch(boolean fetchJoin, String alias, boolean jpaCompliance) {\n    return !fetchJoin || alias == null || alias.startsWith( \"var_\" ) || !jpaCompliance;\n}","tryCatchPattern":null,"preventionTips":["Avoid aliases on fetch joins altogether; navigate from the owning root path.","If you need to sort/filter on the association, add a real join and alias that.","Know your compliance flag: hibernate.jpa.compliance.query flips this from warning-free extension to IllegalStateException.","Only 'var_'-prefixed (Hibernate-generated) aliases pass under compliance."],"tags":["hibernate","criteria-api","fetch-join","alias","jpa-compliance"],"backgroundTag":"jpa-compliance-violation","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}