{"record":{"id":"11f5bf68a92ef55d","repo":"hibernate/hibernate-orm","slug":"passed-attribute-s-did-not-correspond-to-a-join","errorCode":null,"errorMessage":"Passed attribute [%s] did not correspond to a joinable reference [%s] relative to %s","messagePattern":"Passed attribute \\[(.+?)\\] did not correspond to a joinable reference \\[(.+?)\\] relative to (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/AbstractSqmFrom.java","lineNumber":956,"sourceCode":"\n\tprivate <A> SqmAttributeJoin<T, A> buildAttributeJoin(SqmPathSource<A> joinedPathSource, SqmJoinType joinType, boolean fetched) {\n\t\tif ( joinedPathSource instanceof SqmSingularPersistentAttribute<?, A> ) {\n\t\t\treturn buildSingularJoin( (SqmSingularPersistentAttribute<T, A>) joinedPathSource, joinType, fetched );\n\t\t}\n\t\telse if ( joinedPathSource instanceof SqmBagPersistentAttribute<?, A> ) {\n\t\t\treturn buildBagJoin( (SqmBagPersistentAttribute<T, A>) joinedPathSource, joinType, fetched );\n\t\t}\n\t\telse if ( joinedPathSource instanceof SqmListPersistentAttribute<?, A> ) {\n\t\t\treturn buildListJoin( (SqmListPersistentAttribute<T, A>) joinedPathSource, joinType, fetched );\n\t\t}\n\t\telse if ( joinedPathSource instanceof SqmMapPersistentAttribute<?, ?, A> ) {\n\t\t\treturn buildMapJoin( (SqmMapPersistentAttribute<T, ?, A>) joinedPathSource, joinType, fetched );\n\t\t}\n\t\telse if ( joinedPathSource instanceof SqmSetPersistentAttribute<?, A> ) {\n\t\t\treturn buildSetJoin( (SqmSetPersistentAttribute<T, A>) joinedPathSource, joinType, fetched );\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\"Passed attribute [%s] did not correspond to a joinable reference [%s] relative to %s\",\n\t\t\t\t\t\t\tjoinedPathSource.getPathName(),\n\t\t\t\t\t\t\tjoinedPathSource,\n\t\t\t\t\t\t\tgetNavigablePath()\n\t\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate <A> SqmSingularJoin<T, A> buildSingularJoin(\n\t\t\tSqmSingularPersistentAttribute<? super T, A> attribute,\n\t\t\tSqmJoinType joinType,\n\t\t\tboolean fetched) {\n\t\tif ( attribute.getPathType() instanceof ManagedDomainType ) {\n\t\t\treturn new SqmSingularJoin<>(\n\t\t\t\t\tthis,","sourceCodeStart":938,"sourceCodeEnd":974,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/AbstractSqmFrom.java#L938-L974","documentation":"The generic attribute-join builder in AbstractSqmFrom dispatches on the kind of the resolved path source: SqmSingularJoin for singular (association/embedded) attributes and bag/list/map/set builders for the plural kinds. Anything else, i.e. a basic-typed attribute such as a String or Integer column, falls to the final else and throws IllegalArgumentException 'did not correspond to a joinable reference'. Basic values are not joinable in Hibernate criteria.","triggerScenarios":"root.join(root.get(\"name\")) or joining a path whose attribute is a @Basic type (String, Integer, enum, Instant); join(...) on a singular attribute whose type is not an association/embeddable.","commonSituations":"Assuming any path can be joined like in some SQL dialects; missing @ManyToOne/@OneToMany annotations after refactoring so the attribute is basic; porting JPQL/HQL that referenced the column only in WHERE but the translation accidentally used join.","solutions":["Only join association attributes (@ManyToOne/@OneToOne/@OneToMany/@ManyToMany/@ElementCollection).","For basic attributes, use the path in a WHERE predicate (equality, like, in) instead of a join.","If the attribute should be an association, fix the entity mapping (add the relation annotation) and regenerate the metamodel."],"exampleFix":"// before\nroot.join( root.<String>get( \"name\" ) ); // basic attribute -> not joinable\n// after\nquery.where( cb.equal( root.get( \"name\" ), \"Alice\" ) );","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean isJoinable(ManagedType<?> type, String attr) {\n    Attribute<?, ?> a = type.getAttribute( attr );\n    if ( a instanceof jakarta.persistence.metamodel.PluralAttribute ) return true;\n    return a instanceof jakarta.persistence.metamodel.SingularAttribute<?, ?> s\n        && ( s.getType() instanceof jakarta.persistence.metamodel EntityType\n            || s.getType() instanceof jakarta.persistence.metamodel.EmbeddableType );\n}","tryCatchPattern":null,"preventionTips":["Join only association/embedded attributes; filter basic columns with WHERE predicates.","After mapping refactors, verify the attribute is still an association before criteria code joins it.","If a 'join' of a basic column seems necessary, that is usually a missing relation annotation or should be a where condition."],"tags":["hibernate","criteria-api","join","basic-attribute","illegal-argument"],"backgroundTag":"non-joinable-attribute","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}