{"record":{"id":"e93815db034cdc17","repo":"hibernate/hibernate-orm","slug":"proxy-must-be-either-an-interface-or-the-class-it-e93815","errorCode":null,"errorMessage":"proxy must be either an interface, or the class itself: {entityName}","messagePattern":"proxy must be either an interface, or the class itself: (.+?)","errorType":"exception","errorClass":"MappingException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java","lineNumber":262,"sourceCode":"\n\t\tif ( proxyInterface != null && ! mappedClass.equals( proxyInterface ) ) {\n\t\t\tif ( ! proxyInterface.isInterface() ) {\n\t\t\t\tthrow new MappingException( \"proxy must be either an interface, or the class itself: \"\n\t\t\t\t\t\t\t\t\t\t\t+ bootDescriptor.getEntityName() );\n\t\t\t}\n\t\t\tproxyInterfaces.add( proxyInterface );\n\t\t}\n\n\t\tif ( mappedClass.isInterface() ) {\n\t\t\tproxyInterfaces.add( mappedClass );\n\t\t}\n\n\t\tfor ( var subclass : bootDescriptor.getSubclasses() ) {\n\t\t\tfinal var subclassProxy = subclass.getProxyInterface();\n\t\t\tfinal var subclassClass = subclass.getMappedClass();\n\t\t\tif ( subclassProxy != null && !subclassClass.equals( subclassProxy ) ) {\n\t\t\t\tif ( !subclassProxy.isInterface() ) {\n\t\t\t\t\tthrow new MappingException( \"proxy must be either an interface, or the class itself: \"\n\t\t\t\t\t\t\t\t\t\t\t\t+ subclass.getEntityName() );\n\t\t\t\t}\n\t\t\t\tproxyInterfaces.add( subclassProxy );\n\t\t\t}\n\t\t}\n\n\t\tproxyInterfaces.add( HibernateProxy.class );\n\n\t\treturn proxyInterfaces;\n\t}\n\n\tprivate static ProxyFactory instantiateProxyFactory(\n\t\t\tPersistentClass bootDescriptor,\n\t\t\tBytecodeProvider bytecodeProvider,\n\t\t\tRuntimeModelCreationContext creationContext,\n\t\t\tMethod proxyGetIdentifierMethod,\n\t\t\tMethod proxySetIdentifierMethod,\n\t\t\tClass<?> mappedClass,","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java#L244-L280","documentation":"Same validation as the root-entity case, but performed while EntityRepresentationStrategyPojoStandard walks the subclass closure of the hierarchy: for every subclass with a @Proxy/proxy declaration whose proxy class differs from the subclass's own mapped class, that class must be an interface. A concrete class in a subclass's proxy mapping aborts SessionFactory creation with this MappingException naming the offending subclass entity.","triggerScenarios":"@Proxy(proxyClass = ConcreteSubclassHelper.class) on a subclass in a SINGLE_TABLE/JOINED hierarchy; XML <subclass ... proxy=\"...\"> referencing a class; superclass-level proxy interfaces fine but one branch of the hierarchy redeclares @Proxy with a class.","commonSituations":"Large inheritance hierarchies where each subclass declares its own proxy interface and one was refactored from interface to abstract class; merging teams' mappings where conventions differ; proxy annotation inherited/copy-pasted from sibling subclasses.","solutions":["Change the subclass's @Proxy(proxyClass=...) value to an interface the subclass implements","Remove the redundant @Proxy on the subclass if the root declaration already covers it","Use @Proxy(lazy = false) on that subclass when proxying is not wanted"],"exampleFix":"// before\n@Entity\n@Inheritance(strategy = InheritanceType.SINGLE_TABLE)\npublic abstract class BillingDocument { ... }\n\n@Entity\n@Proxy(proxyClass = Invoice.class)   // Invoice is a class, not an interface\npublic class Invoice extends BillingDocument { ... }\n\n// after\n@Entity\n@Proxy(proxyClass = InvoiceDto.class) // interface implemented by Invoice\npublic class Invoice extends BillingDocument implements InvoiceDto { ... }","handlingStrategy":"validation","validationCode":"// Validate the whole hierarchy, not just the root\nfor ( Class<?> c : allMappedClassesInHierarchy() ) {\n    Proxy p = c.getAnnotation(Proxy.class);\n    if ( p != null && !void.class.equals(p.proxyClass()) && !p.proxyClass().isInterface() && !p.proxyClass().equals(c) ) {\n        throw new IllegalStateException(\"Subclass \" + c + \" declares a non-interface @Proxy class\");\n    }\n}","typeGuard":"static boolean isValidSubclassProxy(Class<?> subclass, Class<?> proxyClass) {\n    return proxyClass == null || proxyClass.isInterface() || proxyClass.equals(subclass);\n}","tryCatchPattern":"try {\n    emf = Persistence.createEntityManagerFactory(\"pu\");\n}\ncatch ( org.hibernate.mapping.MappingException e ) {\n    if ( e.getMessage() != null && e.getMessage().startsWith(\"proxy must be either an interface\") ) {\n        // message names the subclass entity - fix that subclass's @Proxy/XML proxy attribute\n        throw new ConfigurationError(\"Invalid proxy mapping in hierarchy: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Audit every subclass @Proxy when refactoring hierarchy types - interfaces can silently become classes","Prefer declaring the proxy interface once on the root entity","Let SessionFactory bootstrap in CI catch hierarchy-wide proxy misconfigurations"],"tags":["hibernate","proxy","inheritance","subclass","mapping","bootstrap"],"backgroundTag":"invalid-proxy-mapping","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}