hibernate/hibernate-orm · error · UnsupportedOperationException
Not a Map-valued attribute node
Error message
Not a Map-valued attribute node
What it means
addKeySubgraph() is implemented only on MapAttributeNodeImpl — the node kind created for Map-valued attributes. Calling it on a singular node or a non-Map collection node hits the base-class implementation and throws UnsupportedOperationException.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java:213
return valueSubgraph;
}
@Override
@Nonnull
public SubGraphImplementor<J> addSingularSubgraph() {
throw new UnsupportedOperationException("Not a singular attribute node");
}
@Override
@Nonnull
public SubGraphImplementor<E> addElementSubgraph() {
throw new UnsupportedOperationException( "Not a collection-valued attribute node" );
}
@Override
@Nonnull
public SubGraphImplementor<K> addKeySubgraph() {
throw new UnsupportedOperationException( "Not a Map-valued attribute node" );
}
protected void checkToOne() {
final Attribute.PersistentAttributeType attributeType = attribute.getPersistentAttributeType();
if ( attributeType != MANY_TO_ONE && attributeType != ONE_TO_ONE && attributeType != EMBEDDED ) {
throw new CannotContainSubGraphException( "Attribute '" + attribute.getName() + "' is not a to-one association" );
}
}
protected void checkToMany() {
final Attribute.PersistentAttributeType attributeType = attribute.getPersistentAttributeType();
if ( attributeType != MANY_TO_MANY && attributeType != ONE_TO_MANY ) {
throw new CannotContainSubGraphException( "Attribute '" + attribute.getName() + "' is not a to-many association" );
}
}
protected <T> ManagedDomainType<T> asManagedType(DomainType<T> domainType) {
if ( domainType instanceof ManagedDomainType<T> managedDomainType ) {View on GitHub (pinned to fad1729dce)
Solutions
- Use addKeySubgraph() only on Map attributes; fetch Map values with addElementSubgraph()
- For non-map collections use addElementSubgraph()
- Guard the call with attr instanceof MapAttribute before invoking
Example fix
// before
graph.addAttributeNode("tags").addKeySubgraph(); // tags is List<String> → throws
// after — key subgraphs exist only for Map attributes
graph.addAttributeNode("settings") // Map<Language, Setting>
.addKeySubgraph(); // Language key subgraph
graph.addAttributeNode("settings")
.addElementSubgraph().addAttributeNode("value"); Defensive patterns
Strategy: type-guard
Validate before calling
if (isMap(node.getAttribute())) {
node.addKeySubgraph(); // keys
node.addElementSubgraph(); // values
} Type guard
static boolean isMap(Attribute<?, ?> attr) {
return attr instanceof jakarta.persistence.metamodel.MapAttribute<?, ?, ?>;
} Prevention
- Call addKeySubgraph() only on Map persistent attributes
- Fetch Map values with addElementSubgraph()
- Check the metamodel kind before calling key/element subgraph methods in generic code
When it happens
Trigger: node.addKeySubgraph() where the attribute is a @OneToMany/@ManyToOne/List/Set/basic — anything that is not a persistent java.util.Map attribute.
Common situations: Adding key-fetching logic to graphs of collections that were Maps in an earlier iteration of the model; generic graph code that calls all three subgraph variants unconditionally.
Related errors
- Not a singular attribute node
- Not a collection-valued attribute node
- No node for attribute: {}
- Duplicate named entity graph '%s'
- The 'root' parameter of the @NamedEntityGraph should be pass
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/2a3ab12854aba435.
Report an issue: GitHub.