hibernate/hibernate-orm · error · IllegalArgumentException

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

Error message

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

What it means

getMap(name)/getDeclaredMap(name) found the attribute but its class is not a MapAttribute implementation — the field is actually a Set, List, or bag. The actual attribute class is included in the message.

Source

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


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Map attributes

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

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

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

	@Override
	@SuppressWarnings("unchecked")
	@Nonnull
	public <K, V> MapAttribute<? super J, K, V> getMap(
			@Nonnull String name,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use getList/getSet/getCollection per the real declaration
  2. Declare the field as Map<K,V> (e.g. @ElementCollection Map<String,String> labels) when map semantics are wanted
  3. Use the message's attributeClass to identify the actual attribute implementation

Example fix

// before
MapPersistentAttribute<Article, String, String> t = articleType.getMap("translations"); // Set field -> throws

// after
SetPersistentAttribute<Article, Translation> t = articleType.getSet("translations");
// or change field to Map<String,String> translations;
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 javax.persistence.metamodel.MapAttribute)) {
    throw new IllegalArgumentException(name + " is not a Map on " + type.getTypeName());
}

Type guard

static boolean isMapAttr(ManagedType<?> type, String name) {
    for (Attribute<?,?> a : type.getAttributes()) {
        if (a.getName().equals(name) && a instanceof javax.persistence.metamodel.MapAttribute) return true;
    }
    return false;
}

Try / catch

try {
    return type.getMap(name);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("is not a MapAttribute")) {
        // real kind is Set/List/Bag — inspect e for attributeClass
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getMap("translations") when translations is declared as Set<Translation> or List<Translation>. Map semantics require java.util.Map<K,V> (or a Hibernate-specific map mapping) on the entity.

Common situations: Refactoring a Map field to a collection of wrapper embeddables without updating metamodel code; expecting getMap to work on @ElementCollection(targetClass=...) list forms.

Related errors


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