hibernate/hibernate-orm · error · UnsupportedOperationException

Not a singular attribute node

Error message

Not a singular attribute node

What it means

AttributeNodeImpl is sealed into singular, plural and map node kinds, and each kind supports only the subgraph methods matching its attribute: addSingularSubgraph() is implemented solely on SingularAttributeNodeImpl. Calling it on a node for a collection attribute (PluralAttributeNodeImpl / MapAttributeNodeImpl) hits the base-class implementation and throws UnsupportedOperationException.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java:201

		return attribute;
	}

	@Override
	@Nonnull
	public SubGraphImplementor<E> addValueSubgraph() {
		verifyMutability();
		setFetchType( FetchType.EAGER );
		// this one is intentionally lenient and disfavored
		if ( valueSubgraph == null ) {
			valueSubgraph = new SubGraphImpl<>( asManagedType( valueGraphType ), true );
		}
		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" );

View on GitHub (pinned to fad1729dce)

Solutions

  1. For collection attributes use addElementSubgraph() (elements) or, for Maps, addKeySubgraph() (keys)
  2. For to-one/embedded attributes use addSingularSubgraph() (or addSubgraph())
  3. In generic builders, branch on the metamodel: if (attr instanceof PluralAttribute) addElementSubgraph else addSingularSubgraph
  4. Check the attribute's PersistentAttributeType before choosing the subgraph method

Example fix

// before — singular subgraph on a collection attribute
graph.addAttributeNode("items").addSingularSubgraph(); // items is @OneToMany → throws

// after — subgraph over the collection elements
graph.addAttributeNode("items")
     .addElementSubgraph()
     .addAttributeNode("product");
Defensive patterns

Strategy: type-guard

Validate before calling

// Dispatch on the attribute kind instead of calling addSingularSubgraph unconditionally
if (isSingular(node.getAttribute())) {
    node.addSingularSubgraph().addAttributeNode("name");
}
else {
    node.addElementSubgraph().addAttributeNode("name");
}

Type guard

static boolean isSingular(Attribute<?, ?> attr) {
    return !(attr instanceof jakarta.persistence.metamodel.PluralAttribute<?, ?, ?>);
}

Prevention

When it happens

Trigger: Calling node.addSingularSubgraph() — or the convenience addSubgraph(), which delegates to addSingularSubgraph() — on an attribute node obtained for a @OneToMany, @ManyToMany or @ElementCollection attribute, e.g. graph.addAttributeNode("items").addSingularSubgraph().

Common situations: Generic graph-building code that unconditionally calls addSubgraph for every node; refactoring a to-one into a to-many without updating graph code; adopting the JPA 3.2 addSingularSubgraph/addElementSubgraph pair and calling the wrong variant.

Related errors


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