hibernate/hibernate-orm · error · HibernateException

Attribute was not a Map : ${collectionMemberType}

Error message

Attribute was not a Map : ${collectionMemberType}

What it means

Hibernate throws this HibernateException while binding metadata, inside AutoApplicableConverterDescriptorStandardImpl.getAutoAppliedConverterDescriptorForMapKey. When a converter with autoApply=true is considered for the KEY of a map-style plural attribute, Hibernate resolves the attribute's actual member type and requires it to be assignable to java.util.Map; if the member resolves to some other type (List, Set, array, a raw type, or a custom collection), the internal invariant is broken and binding fails.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/convert/internal/AutoApplicableConverterDescriptorStandardImpl.java:110

	}

	@Override
	public ConverterDescriptor<?,?> getAutoAppliedConverterDescriptorForMapKey(
			MemberDetails memberDetails,
			MetadataBuildingContext context) {

		final var collectionMemberType = actualMemberType( memberDetails );
		final Type keyType;
		if ( Map.class.isAssignableFrom( erasedType( collectionMemberType ) ) ) {
			final var typeArguments =
					typeArguments( Map.class, collectionMemberType );
			if ( typeArguments.length == 0 ) {
				return null;
			}
			keyType = typeArguments[0];
		}
		else {
			throw new HibernateException( "Attribute was not a Map : " + collectionMemberType );
		}

		return isAssignableFrom( linkedConverterDescriptor.getDomainValueResolvedType(),
						canonicalizePrimitive( keyType ) )
				? linkedConverterDescriptor
				: null;
	}


}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Declare the plural attribute as Map<KeyType, ValueType> if the map-key converter is intended to apply
  2. If the attribute is intentionally a List/Set/array, stop the converter from auto-applying to it with @Convert(disableConversion = true) on the attribute or @Converter(autoApply = false)
  3. Narrow the converter's domain type so it no longer matches the attribute's key type, or register it explicitly with @Convert instead of autoApply
  4. If the member is a custom collection type, make sure its class ultimately implements java.util.Map when used where a map key is expected
  5. Report to Hibernate (HHH) if the attribute is a plain Map and it still fails - a resolution bug in auto-apply handling

Example fix

// before: auto-apply converter + non-Map plural attribute
@Converter(autoApply = true)
public class StatusConverter implements AttributeConverter<Status, String> { ... }

@Entity
class Order {
    @ElementCollection
    private List<Status> statuses = new ArrayList<>();  // triggers map-key resolution internally
}

// after: either use a Map so map-key auto-apply is well-defined
@ElementCollection
private Map<Status, Integer> statusCounts = new HashMap<>();

// ...or exclude the attribute from auto-apply
@Convert(disableConversion = true)
@ElementCollection
private List<Status> statuses = new ArrayList<>();
Defensive patterns

Strategy: type-guard

Validate before calling

// Before boot: every attribute that map-key converter resolution will visit must be a Map
static boolean allPluralMapAttributesAreMaps(Class<?> entity) {
    for (Field f : entity.getDeclaredFields()) {
        if (f.isAnnotationPresent(ElementCollection.class)
                || f.isAnnotationPresent(OneToMany.class)
                || f.isAnnotationPresent(ManyToMany.class)) {
            if (f.isAnnotationPresent(MapKey.class)
                    || f.isAnnotationPresent(MapKeyClass.class)
                    || f.isAnnotationPresent(MapKeyEnumerated.class)) {
                if (!Map.class.isAssignableFrom(f.getType())) return false;
            }
        }
    }
    return true;
}

Type guard

// Type guard usable on a single suspected field
static boolean isMapAttribute(Field f) {
    return Map.class.isAssignableFrom(f.getType());
}

Try / catch

try {
    sessionFactory = new MetadataSources(registry).addAnnotatedClass(Order.class)
            .buildMetadata().buildSessionFactory();
} catch (HibernateException e) {  // "Attribute was not a Map" surfaces here
    throw new IllegalStateException("Bad plural-attribute shape for auto-apply converter: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: A @Converter(autoApply=true) converter is registered (via @Converter, MetadataBuilder.addAttributeConverter, or autoApplyDetection) and Hibernate resolves map-key auto-apply for a plural attribute whose declared/actual type is not java.util.Map, e.g. a List/Set field processed through map-key converter resolution, or a custom collection implementation masking the Map interface.

Common situations: Upgrading Hibernate between 6.x and 7.x where auto-apply resolution for collection keys/elements was reworked; introducing an autoApply converter into a codebase that already uses custom collection types; generics erased by proxying or raw types.

Related errors


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