hibernate/hibernate-orm · critical · UnsupportedMappingException
Unknown collection: {}
Error message
Unknown collection: {} What it means
PluralAttributeBuilder.build builds the JPA PluralAttribute for a mapped collection attribute. After strict matching (exact Map/List/Collection) and loose matching (arrays, then assignable Map/Set/List/Collection), a declared Java collection type that falls through every branch throws UnsupportedMappingException('Unknown collection: ' + javaType) at bootstrap. In practice that means a type that is not a Map/Set/List/Collection or array — most commonly a type implementing only Iterable.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/PluralAttributeBuilder.java:121
//apply loose rules
if ( javaClass.isArray() ) {
return new ListAttributeImpl( builder );
}
if ( Map.class.isAssignableFrom( javaClass ) ) {
return new MapAttributeImpl( builder );
}
else if ( Set.class.isAssignableFrom( javaClass ) ) {
return new SetAttributeImpl( builder );
}
else if ( List.class.isAssignableFrom( javaClass ) ) {
return new ListAttributeImpl( builder );
}
else if ( Collection.class.isAssignableFrom( javaClass ) ) {
return new BagAttributeImpl( builder );
}
throw new UnsupportedMappingException( "Unknown collection: " + attributeJtd.getJavaType() );
}
private static SimpleDomainType<?> determineListIndexOrMapKeyType(
PluralAttributeMetadata<?,?,?> attributeMetadata,
MetadataContext metadataContext) {
final var javaType = attributeMetadata.getJavaType();
if ( Map.class.isAssignableFrom( javaType ) ) {
return (SimpleDomainType<?>)
determineSimpleType( attributeMetadata.getMapKeyValueContext(), metadataContext );
}
if ( List.class.isAssignableFrom( javaType ) || javaType.isArray() ) {
return metadataContext.getTypeConfiguration().getBasicTypeRegistry()
.getRegisteredType( Integer.class );
}
return null;
}View on GitHub (pinned to fad1729dce)
Solutions
- Declare the attribute as one of java.util.Collection, List, Set, or Map (or a primitive array) — e.g. change Iterable<Order> to List<Order>
- For custom collection wrappers, expose a standard JDK collection type on the mapped property and adapt elsewhere
- If the type was never meant to be a persistent collection, remove the association annotation
Example fix
// before @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private Iterable<OrderLine> lines; // UnsupportedMappingException: Unknown collection // after @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List<OrderLine> lines;
Defensive patterns
Strategy: validation
Validate before calling
// Startup scan: reject association attributes whose Java type is not a mappable collection
for (Class<?> c : scannedEntityClasses) {
for (java.lang.reflect.Field f : c.getDeclaredFields()) {
boolean isAssociation = f.isAnnotationPresent(OneToMany.class)
|| f.isAnnotationPresent(ManyToMany.class)
|| f.isAnnotationPresent(ElementCollection.class);
if (isAssociation) {
Class<?> t = f.getType();
boolean ok = t.isArray() || Map.class.isAssignableFrom(t) || Collection.class.isAssignableFrom(t);
if (!ok) {
throw new IllegalStateException("Association field " + f
+ " must be Map/Set/List/Collection/array, not " + t.getName());
}
}
}
} Type guard
static boolean isMappableCollectionType(Class<?> t) {
return t.isArray() || Map.class.isAssignableFrom(t) || Collection.class.isAssignableFrom(t);
} Prevention
- Declare persistent collection fields as java.util List/Set/Collection/Map — never Iterable or custom wrappers
- Expose custom/read-model types only on getters of non-mapped copies, keep the mapped field standard
- Run the annotation-vs-field-type scan above as a unit test over the entity package
When it happens
Trigger: An @OneToMany/@ManyToMany/@ElementCollection attribute declared as Iterable<T>, Queue handled? (no — Queue extends Collection so it matches Bag), but Iterable<T>, or a custom collection class implementing only Iterable; an attribute whose getter returns a non-JDK-collection type due to wrong mapping on the wrong field.
Common situations: Domain models using Iterable for read models then annotated as associations; custom Bag/List abstractions that only extend Iterable; IDE-generated fields typed Iterable; Kotlin/Scala collection types not bridged to java.util types in mappings.
Related errors
- Encountered multiple component mappings for the same java cl
- Cannot resolve entity class : {}
- one-to-many collections with identifiers are not supported
- must be an BeforeExecutionGenerator
- Could not resolve named query '{}' for loading collection '{
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b929602b5cb1ca82.
Report an issue: GitHub.