hibernate/hibernate-orm · error · IllegalArgumentException

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

Error message

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

What it means

getSet(name)/getDeclaredSet(name) found the attribute but its concrete class is not a SetPersistentAttribute — typically it is a Bag (Collection), List, or Map attribute implementation. Hibernate includes the actual attribute class in the message.

Source

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


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Set attributes

	@Override
	@SuppressWarnings("unchecked")
	@Nonnull
	public SetPersistentAttribute<? super J, ?> getSet(@Nonnull String name) {
		final var attribute = findPluralAttribute( name );
		basicSetCheck( attribute, name );
		assert attribute != null;
		return (SetPersistentAttribute<? super J, ?>) attribute;
	}

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

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

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

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use getList/getCollection/getMap according to the actual declaration
  2. Change the entity field to java.util.Set if set semantics are wanted (and re-check equals/hashCode of the element type)
  3. Derive the accessor dynamically from attribute.getCollectionType()

Example fix

// before
SetPersistentAttribute<Post, String> tags = postType.getSet("tags"); // List<String> field -> throws

// after
ListPersistentAttribute<Post, String> tags = postType.getList("tags");
// or change field: Set<String> tags;
Defensive patterns

Strategy: type-guard

Validate before calling

var attr = StreamSupport.stream(type.getAttributes().spliterator(), false)
        .filter(a -> a.getName().equals(name)).findFirst().orElse(null);
if (!(attr instanceof org.hibernate.metamodel.model.domain.SetPersistentAttribute)) {
    throw new IllegalArgumentException(name + " is not a Set on " + type.getTypeName());
}

Type guard

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

Try / catch

try {
    return type.getSet(name);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("is not a SetAttribute")) {
        return null; // or route to getList/getCollection based on real kind
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getSet("tags") on a field declared as Collection<String>, List<String>, or Map<...>. Set semantics (unique elements) only exist for Set/PersistentSet mappings.

Common situations: Field declared as List or Collection while the code assumes a Set; switching collection types during refactoring without updating metamodel accessors.

Related errors


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