hibernate/hibernate-orm · error · CannotContainSubGraphException

Attribute '{}' is of type '{}' which is not a managed type

Error message

Attribute '{}' is of type '{}' which is not a managed type

What it means

Creating a subgraph requires the target type to be a managed type (entity or embeddable): asManagedType() casts the DomainType to ManagedDomainType and throws CannotContainSubGraphException when it is a basic type. It is reached from the lenient addValueSubgraph() (which does not run checkToOne first) and from addKeySubgraph() when a Map's key type is basic.

Source

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

		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 ) {
			return managedDomainType;
		}
		else {
			throw new CannotContainSubGraphException( "Attribute '" + description()
					+ "' is of type '" + domainType.getTypeName()
					+ "' which is not a managed type" );
		}
	}

	private String description() {
		return attribute.getDeclaringType().getTypeName() + "." + attribute.getName();
	}

	@Override
	public String toString() {
		return "AttributeNode[" + description() + "]";
	}

	@Override
	public void merge(@Nonnull AttributeNodeImplementor<J, E, K> that) {
		assert that.isMutable() == isMutable();
		assert that.getAttributeDescriptor() == attribute;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add subgraphs only where the target is an entity or embeddable type
  2. For collections of basic values, just add the attribute node — there is nothing nested to fetch
  3. For Maps with basic keys, fetch the map eagerly instead of using addKeySubgraph()
  4. Guard generic builders by checking that the relevant type is a ManagedType via the metamodel

Example fix

// before — key subgraph on a basic map key
graph.addAttributeNode("settings")   // Map<String, Setting>
     .addKeySubgraph();               // key type String is basic → CannotContainSubGraphException

// after — key subgraphs need managed key types; basic keys: just fetch the map
graph.addAttributeNode("settings");
// Map<Language, Setting> with @Embeddable Language → addKeySubgraph() works
Defensive patterns

Strategy: type-guard

Validate before calling

// For map keys: only managed key types can carry a key subgraph
if (mm.managedType(Settings.class).getAttribute("settings") instanceof MapAttribute<?, ?, ?> map
        && isManagedTarget(map.getKeyType())) {
    node.addKeySubgraph();
}

Type guard

static boolean isManagedTarget(jakarta.persistence.metamodel.Type<?> type) {
    return type instanceof jakarta.persistence.metamodel.ManagedType<?>;
}

Prevention

When it happens

Trigger: Calling addValueSubgraph() on a node whose value graph type is basic (String, enum, Instant), or addKeySubgraph() on a Map keyed by a basic type (Map<String, Setting>) — the SubGraphImpl creation fails in asManagedType because a basic domain type has no attributes to descend into.

Common situations: Graph builders that add subgraphs for every node; collections of basic values where developers expect nested attribute control; map-key subgraphs on String/enum keys.

Related errors


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