hibernate/hibernate-orm · error · IllegalArgumentException

${name} is not a CollectionAttribute: ${attributeClass}

Error message

${name} is not a CollectionAttribute: ${attributeClass}

What it means

getCollection(name)/getDeclaredCollection(name) found an attribute by that name, but it is not a bag-style CollectionPersistentAttribute — e.g. it is a Set, List, or Map attribute. Hibernate reports the actual attribute class so you can see which collection kind it really is.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractManagedType.java:483

	// Bags

	@Override
	@SuppressWarnings("unchecked")
	@Nonnull
	public BagPersistentAttribute<? super J, ?> getCollection(@Nonnull String name) {
		var attribute = findPluralAttribute( name );
		if ( attribute == null && getSuperType() != null ) {
			attribute = getSuperType().findPluralAttribute( name );
		}
		basicCollectionCheck( attribute, name );
		assert attribute != null;
		return (BagPersistentAttribute<J, ?>) attribute;
	}

	private void basicCollectionCheck(PluralAttribute<? super J, ?, ?> attribute, String name) {
		checkNotNull( "CollectionAttribute", attribute, name );
		if ( ! BagPersistentAttribute.class.isAssignableFrom( attribute.getClass() ) ) {
			throw new IllegalArgumentException( name + " is not a CollectionAttribute: " + attribute.getClass() );
		}
	}

	@Override
	@SuppressWarnings( "unchecked")
	@Nonnull
	public CollectionAttribute<J, ?> getDeclaredCollection(@Nonnull String name) {
		final var attribute = findDeclaredPluralAttribute( name );
		basicCollectionCheck( attribute, name );
		assert attribute != null;
		return ( CollectionAttribute<J, ?> ) attribute;
	}

	@Override
	@SuppressWarnings("unchecked")
	@Nonnull
	public <E> BagPersistentAttribute<? super J, E> getCollection(@Nonnull String name, @Nonnull Class<E> elementType) {
		final var attribute = findPluralAttribute( name );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use the accessor matching the declaration: getSet for Set, getList for List, getMap for Map
  2. Declare the field as java.util.Collection (or List without @OrderColumn semantics per JPA) if bag semantics are intended
  3. Inspect attributeClass from the message to identify the real kind before fixing the call

Example fix

// before
CollectionAttribute<Order, Item> items = orderType.getCollection("items"); // items is List<Item> -> throws

// after
ListAttribute<Order, Item> items = orderType.getList("items");
Defensive patterns

Strategy: type-guard

Validate before calling

var attr = type.findPluralAttribute(name); // or walk getAttributes()
if (attr == null || !(attr instanceof org.hibernate.metamodel.model.domain.BagPersistentAttribute)) {
    throw new IllegalArgumentException(name + " is not a bag on " + type.getTypeName());
}

Type guard

static boolean isBag(ManagedType<?> type, String name) {
    for (Attribute<?,?> a : type.getAttributes()) {
        if (a.getName().equals(name)
                && a instanceof org.hibernate.metamodel.model.domain.BagPersistentAttribute) return true;
    }
    return false;
}

Try / catch

try {
    return type.getCollection(name);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("is not a CollectionAttribute")) {
        // attribute is a Set/List/Map — use the matching accessor
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getCollection("orders") when Order.orders is declared as Set<Order> or List<Order>. The bag semantics of CollectionAttribute (unordered, no index, duplicates allowed) only fit Collection/Bag declarations.

Common situations: Declaring fields as Set or List (most common) and assuming getCollection is a generic 'any collection' accessor. Changing collection kinds during refactoring. Reading the error's attributeClass tells you the concrete type (SetPersistentAttributeImpl etc.) — map to the right accessor.

Related errors


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