hibernate/hibernate-orm · error · IllegalArgumentException
Passed attribute name [%s] did not correspond to a collectio
Error message
Passed attribute name [%s] did not correspond to a collection (set) reference [%s] relative to %s
What it means
AbstractSqmFrom.joinSet(attributeName, joinType) requires the resolved attribute to be a SetPersistentAttribute (java.util.Set mapping). Any other kind (bag/Collection, ordered List, Map, singular attribute) throws IllegalArgumentException with the attribute name, the resolved source and the navigable path.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/AbstractSqmFrom.java:571
return joinSet( attributeName, JoinType.INNER );
}
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <Y> SqmSetJoin<T, Y> joinSet(@Nonnull String attributeName, @Nonnull JoinType jt) {
final var joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName );
if ( joinedPathSource instanceof SetPersistentAttribute ) {
final var join = buildSetJoin(
(SetPersistentAttribute<T, Y>) joinedPathSource,
SqmJoinType.from( jt ),
false
);
addSqmJoin( join );
return join;
}
throw new IllegalArgumentException(
String.format(
Locale.ROOT,
"Passed attribute name [%s] did not correspond to a collection (set) reference [%s] relative to %s",
attributeName,
joinedPathSource,
getNavigablePath()
)
);
}
@Nonnull
@Override
public <Y> SqmListJoin<T, Y> joinList(@Nonnull String attributeName) {
return joinList( attributeName, JoinType.INNER );
}
@Nonnull
@OverrideView on GitHub (pinned to fad1729dce)
Solutions
- Use joinCollection for Collection/bag, joinList for ordered List, joinMap for Map, join for singular attributes.
- Use the typed metamodel overloads join(SetAttribute) etc. so the compiler catches the mismatch.
- Inspect the attribute via the metamodel (instanceof SetAttribute) before calling.
Example fix
// before customerRoot.joinSet( "orders", JoinType.INNER ); // orders is List<Order> // after customerRoot.joinList( "orders", JoinType.INNER );
Defensive patterns
Strategy: type-guard
Type guard
static boolean isSet(ManagedType<?> type, String attr) {
return type.getAttribute( attr ) instanceof jakarta.persistence.metamodel.SetAttribute;
} Prevention
- Use join(SetAttribute) typed overloads from the metamodel where possible.
- Guard string-based joinSet calls with a SetAttribute instanceof check.
- Keep entity container types stable, or centralize join creation so kind changes only touch one place.
When it happens
Trigger: root.joinSet("tags", JoinType.INNER) when tags is List<String> or Collection<String>; joinSet on a Map attribute or a singular @ManyToOne attribute.
Common situations: Field migrated from Set to List; generic helpers calling joinSet unconditionally; assuming 'set' means any collection.
Related errors
- Passed attribute name [%s] did not correspond to a collectio
- Passed attribute name [%s] did not correspond to a collectio
- Passed attribute [%s] did not correspond to a joinable refer
- Illegal empty CTE name
- Illegal CTE name [%s]. Names must start with an alphabetic c
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/6308965fedf16c79.
Report an issue: GitHub.