hibernate/hibernate-orm · critical · IllegalArgumentException

Cannot resolve entity class : {}

Error message

Cannot resolve entity class : {}

What it means

Hibernate throws this IllegalArgumentException while applying @NamedEntityGraph definitions during SessionFactory/EntityManagerFactory bootstrap. JpaMetamodelImpl.applyNamedEntityGraphs resolves every entity class referenced by the graph (root and subgraphs) against managedTypeByClass; a class that is not a registered managed type aborts startup. The graphCreator lambda has no fallback: any non-entity class in a @NamedSubgraph(type=...) triggers the throw.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java:517

					final var info = new ImportInfo( name, loadedClass );
					nameToImportMap.put( name, info );
					return info;
				}
			}
		}
	}

	private void applyNamedEntityGraphs(Collection<NamedEntityGraphDefinition> namedEntityGraphs) {
		for ( var definition : namedEntityGraphs ) {
			CORE_LOGGER.tracef( "Applying named entity graph [name=%s, source=%s]",
					definition.name(), definition.source() );

			final var graph = definition.graphCreator().createEntityGraph(
					entityClass -> {
						if ( managedTypeByClass.get( entityClass ) instanceof EntityDomainType<?> match ) {
							return match;
						}
						throw new IllegalArgumentException( "Cannot resolve entity class : " + entityClass.getName() );
					},
					jpaEntityName -> {
						for ( var entry : managedTypeByName.entrySet() ) {
							if ( entry.getValue() instanceof EntityDomainType<?> possibility
									&& jpaEntityName.equals( possibility.getName() ) ) {
								return possibility;
							}
						}
						throw new IllegalArgumentException( "Cannot resolve entity name : " + jpaEntityName );
					},
					serviceRegistry
			);
			entityGraphMap.put( definition.name(), graph );
		}
	}


	private Class<?> resolveRequestedClass(String entityName) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make every class used in @NamedSubgraph(type=...) a real @Entity in the same persistence unit
  2. If the subgraph targets an @Embedded attribute, restructure the graph so the @NamedSubgraph is typed with the embedding entity and attribute nodes walk into the embeddable
  3. Verify the class is actually picked up by the persistence unit (persistence.xml <class> entries, package auto-detection, or the Spring-equivalent entity scan)
  4. Delete stale @NamedEntityGraph/@NamedSubgraph definitions that reference classes no longer mapped

Example fix

// before
@NamedEntityGraph(
  name = "order-graph",
  attributeNodes = @NamedAttributeNode(value = "items", subgraph = "items-subgraph")),
  subgraphs = @NamedSubgraph(
    name = "items-subgraph",
    type = OrderLineId.class /* not an @Entity */) // throws 'Cannot resolve entity class'

// after
@NamedEntityGraph(
  name = "order-graph",
  attributeNodes = @NamedAttributeNode(value = "items", subgraph = "items-subgraph")),
  subgraphs = @NamedSubgraph(
    name = "items-subgraph",
    type = OrderLine.class /* @Entity */)  // or drop the subgraph and rely on default fetch
Defensive patterns

Strategy: validation

Validate before calling

// Before building the EntityManagerFactory, verify every @NamedSubgraph type is a mapped @Entity
for (Class<?> entity : scannedEntityClasses) {
  for (jakarta.persistence.NamedEntityGraph graph : entity.getAnnotationsByType(jakarta.persistence.NamedEntityGraph.class)) {
    for (jakarta.persistence.NamedSubgraph sub : graph.subgraphs()) {
      if (!sub.type().isAnnotationPresent(jakarta.persistence.Entity.class)) {
        throw new IllegalStateException(
          "Graph on " + entity.getName() + " references non-entity subgraph type " + sub.type().getName());
      }
    }
  }
}

Try / catch

try {
  emf = Persistence.createEntityManagerFactory(puName);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Cannot resolve entity class")) {
    throw new IllegalStateException("Bad @NamedEntityGraph subgraph type (not an @Entity): " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: An @NamedEntityGraph on an entity declares @NamedSubgraph(type = X.class) where X is not an @Entity in the same persistence unit (a DTO, @MappedSuperclass, embeddable, or entity from another PU); an XML <entity-graph> or orm.xml graph referencing an unmanaged class; a graph definition copied from another mapping where the class is no longer mapped.

Common situations: Subgraph type accidentally points at the embeddable instead of the embedding entity; refactor renamed or moved the target class but the graph still references the old one; entity classes listed explicitly in persistence.xml and the graph target was never added; splitting one PU into two leaves the graph in a PU that no longer maps the referenced class.

Related errors


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