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
	@Override

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use joinCollection for Collection/bag, joinList for ordered List, joinMap for Map, join for singular attributes.
  2. Use the typed metamodel overloads join(SetAttribute) etc. so the compiler catches the mismatch.
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/6308965fedf16c79. Report an issue: GitHub.