hibernate/hibernate-orm · error · IllegalArgumentException
Only embeddables without collections are supported!
Error message
Only embeddables without collections are supported!
What it means
When a dynamic instantiation / tuple selection (select new, criteria tuple/array) is reused as an embeddable-valued model part, Hibernate builds an AnonymousTupleEmbeddableValuedModelPart by iterating the embeddable's attributes. Each attribute must be a SingularPersistentAttribute — anonymous tuple model parts only support embeddables made of singular (basic/embeddable/entity) attributes. Any plural attribute (@OneToMany, @ManyToMany, @ElementCollection) inside the embeddable fails with IllegalArgumentException.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tuple/internal/AnonymousTupleEmbeddableValuedModelPart.java:123
this.domainType = domainType;
this.componentName = componentName;
this.existingModelPartContainer = existingModelPartContainer;
this.fetchableIndex = fetchableIndex;
}
private Map<String, ModelPart> createModelParts(
SqmExpressible<?> sqmExpressible,
SqlTypedMapping[] sqlTypedMappings,
int selectionIndex,
String selectionExpression,
Set<String> compatibleTableExpressions,
Set<? extends Attribute<?, ?>> attributes,
EmbeddableValuedModelPart modelPartContainer) {
final Map<String, ModelPart> modelParts = CollectionHelper.linkedMapOfSize( attributes.size() );
int index = 0;
for ( Attribute<?, ?> attribute : attributes ) {
if ( !( attribute instanceof SingularPersistentAttribute<?, ?> ) ) {
throw new IllegalArgumentException( "Only embeddables without collections are supported!" );
}
final DomainType<?> attributeType = ( (SingularPersistentAttribute<?, ?>) attribute ).getType();
final ModelPart modelPart = AnonymousTupleTableGroupProducer.createModelPart(
this,
sqmExpressible,
attributeType,
sqlTypedMappings,
selectionIndex + index,
selectionExpression + "_" + attribute.getName(),
attribute.getName(),
modelPartContainer.findSubPart( attribute.getName(), null ),
compatibleTableExpressions,
index++
);
modelParts.put( modelPart.getPartName(), modelPart );
}
return modelParts;
}View on GitHub (pinned to fad1729dce)
Solutions
- Remove the collection from the embeddable (embeddables with collections are a fragile mapping in general); model the collection on the owning entity instead
- Project only the singular attributes into the tuple and map the result to a DTO class rather than the embeddable
- Select the embeddable directly from its owning entity path rather than reconstructing it through a tuple/dynamic instantiation
Example fix
// before
@Embeddable
class Address {
String city;
@ElementCollection
Set<String> phoneNumbers; // plural attribute breaks anonymous tuple part
}
// after
@Embeddable
class Address {
String city;
}
// move phone numbers to the owning @Entity as @ElementCollection Defensive patterns
Strategy: validation
Validate before calling
// Guard at mapping time: embeddables used in tuple/CTE projections must be singular-only
boolean hasPlural = embeddableType.getAttributes().stream().anyMatch(a -> !a.isCollection() == false); // i.e. a.isCollection()
if (hasPlural) throw new IllegalArgumentException("Embeddable " + embeddableType.getJavaType() + " has collection attributes; unsupported in tuple projections"); Type guard
static boolean isSingularOnly(ManagedType<?> type) { return type.getAttributes().stream().noneMatch(Attribute::isCollection); } Try / catch
try { /* build tuple-typed query using the embeddable */ } catch (IllegalArgumentException e) { if (e.getMessage().contains("without collections")) { /* project singular attrs into a DTO instead */ } else throw e; } Prevention
- Keep embeddables used in CTE/tuple projections free of @ElementCollection/@OneToMany/@ManyToMany
- Add an ArchUnit/mapping test asserting value embeddables contain only singular attributes
- Prefer DTO classes for tuple projections over domain embeddables
When it happens
Trigger: Projecting a tuple/CTE result whose type is an embeddable that contains a collection attribute, then using that tuple as an embeddable-valued path (e.g., CTE attribute typed as the embeddable, or a select-new instantiation later navigated as embeddable).
Common situations: Value-object embeddables that grew a @ElementCollection over time; criteria/HQL queries with CTEs typed by domain embeddables; upgrading to Hibernate 6 where anonymous tuple model parts now validate attributes strictly.
Related errors
- AnonymousTupleEmbeddableValuedModelPart is not fetchable
- Anonymous tuple path source does not have a declaring type
- Unsupported path source: ${domainType}
- Unsupported path source: ${sqmPathType}
- Not yet implemented
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7688e1eb4b8fec7c.
Report an issue: GitHub.