{"record":{"id":"9fad701e2af22829","repo":"hibernate/hibernate-orm","slug":"could-not-resolve-entity-class","errorCode":null,"errorMessage":"Could not resolve entity class '{}'","messagePattern":"Could not resolve entity class '(.+?)'","errorType":"exception","errorClass":"EntityTypeException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java","lineNumber":572,"sourceCode":"\t\tif ( proxyEntityName != null ) {\n\t\t\treturn entity( proxyEntityName );\n\t\t}\n\n\t\t// otherwise, try to handle it as a polymorphic reference\n\t\tfinal var polymorphicDomainType =\n\t\t\t\t\t\tpolymorphicEntityReferenceMap.get( javaType );\n\t\tif ( polymorphicDomainType != null ) {\n\t\t\treturn polymorphicDomainType;\n\t\t}\n\t\telse {\n\t\t\tfinal var polymorphicRootDescriptor =\n\t\t\t\t\tcreatePolymorphicRootDescriptor( javaType );\n\t\t\tif ( polymorphicRootDescriptor != null ) {\n\t\t\t\treturn polymorphicRootDescriptor;\n\t\t\t}\n\t\t}\n\n\t\tthrow new EntityTypeException(\n\t\t\t\t\"Could not resolve entity class '\" + javaType.getName() + \"'\",\n\t\t\t\tjavaType.getName()\n\t\t);\n\t}\n\n\tprivate <T> @Nullable SqmPolymorphicRootDescriptor<T> createPolymorphicRootDescriptor(Class<T> javaType) {\n\t\t// create a set of descriptors that should be used to build the polymorphic EntityDomainType\n\t\tfinal Set<EntityDomainType<? extends T>> matchingDescriptors = new HashSet<>();\n\t\tfor ( var managedType : managedTypeByName.values() ) {\n\t\t\tif ( managedType.getPersistenceType() == Type.PersistenceType.ENTITY\n\t\t\t\t// see if we should add EntityDomainType as one of the matching descriptors.\n\t\t\t\t&& javaType.isAssignableFrom( managedType.getJavaType() ) ) {\n\t\t\t\t// The queried type is assignable from the type of the current entity type.\n\t\t\t\t// We should add it to the collecting set of matching descriptors. It should\n\t\t\t\t// be added aside from a few cases...\n\n\t\t\t\t// If the managed type has a supertype and the java type is assignable from the super type,\n\t\t\t\t// do not add the managed type as the supertype itself will get added and the initializers","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java#L554-L590","documentation":"JpaMetamodelImpl throws EntityTypeException('Could not resolve entity class') when asked for an EntityDomainType for a Java class that is neither itself a registered entity nor has any registered entity subclass (createPolymorphicRootDescriptor finds zero matching descriptors). This is the JPA metamodel/SQM entry point — entity(Class), criteria roots, and graph creation all funnel through it.","triggerScenarios":"Calling emf.getMetamodel().entity(NonEntity.class) or criteriaBuilder.createQuery(X.class).from(X.class) where X is a DTO, @MappedSuperclass, or interface with no @Entity implementors; passing a class that lives in another persistence unit; passing java.lang.Object or a projection class as the query domain.","commonSituations":"Developer expects @MappedSuperclass or a plain interface to behave like a polymorphic @Entity root; a query root class was refactored into a DTO; the class is mapped in a different EntityManagerFactory (multi-PU setup); the entity was excluded from scanning.","solutions":["Pass a class that is annotated @Entity and mapped in the same persistence unit","For polymorphic queries over a hierarchy, make the common supertype an @Entity with an @Inheritance strategy, or query any @Entity subclass — Hibernate builds a polymorphic descriptor when at least one entity subclass is assignable","For interfaces, add at least one @Entity implementation or map the interface as a proxy (@Proxy) so it resolves","Double-check which persistence unit / entity scan the class is actually in"],"exampleFix":"// before\nCriteriaQuery<Auditable> q = cb.createQuery(Auditable.class); // Auditable is a plain interface\nRoot<Auditable> r = q.from(Auditable.class); // throws EntityTypeException\n\n// after\n@Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE)\npublic abstract class Auditable { ... }\n// then query the mapped hierarchy root\nCriteriaQuery<Auditable> q = cb.createQuery(Auditable.class);\nRoot<Auditable> r = q.from(Auditable.class);","handlingStrategy":"validation","validationCode":"<T> EntityType<T> entityOrThrow(Metamodel metamodel, Class<T> cls) {\n  return metamodel.getEntities().stream()\n      .filter(e -> cls.equals(e.getJavaType()))\n      .map(e -> (EntityType<T>) e)\n      .findFirst()\n      .orElseThrow(() -> new IllegalArgumentException(\n          \"Not a mapped entity: \" + cls + \". Known: \" +\n              metamodel.getEntities().stream().map(Type::getJavaType).toList()));\n}\n// use: entityOrThrow(emf.getMetamodel(), cls) instead of emf.getMetamodel().entity(cls)","typeGuard":"static boolean isResolvableEntity(Metamodel metamodel, Class<?> cls) {\n  if (cls.isAnnotationPresent(jakarta.persistence.Entity.class)) return true;\n  // polymorphic fallback: at least one entity subclass assignable\n  return metamodel.getEntities().stream().anyMatch(e -> cls.isAssignableFrom(e.getJavaType()));\n}","tryCatchPattern":"try {\n  EntityType<X> t = emf.getMetamodel().entity(cls);\n} catch (jakarta.persistence.metamodel.TypeNotFoundException | EntityTypeException e) { // Hibernate: org.hibernate.metamodel.EntityTypeException\n  throw new IllegalArgumentException(cls + \" is not an entity in this persistence unit; fix the query domain type\", e);\n}","preventionTips":["Use typed criteria roots (cb.createQuery(Entity.class).from(Entity.class)) so non-entity roots fail at compile time","Constrain generic repository type parameters with an @Entity marker bound","In multi-PU apps, assert expected entities exist per factory at startup: metamodel.getEntities() vs a checklist"],"tags":["hibernate","jpa","metamodel","criteria-api","entity-resolution"],"backgroundTag":"unknown-entity-class","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}