hibernate/hibernate-orm · error · MappingException
proxy must be either an interface, or the class itself: {}
Error message
proxy must be either an interface, or the class itself: {} What it means
A org.hibernate.mapping.MappingException thrown while Hibernate builds the proxy interface set for a POJO entity (EntityRepresentationStrategyPojoStandard, HHH-17578-related logic). If a @Proxy(proxyClass=...) declaration (or <proxy interface=...>) on the root entity names a class that is neither an interface nor the entity's own mapped class, the mapping is invalid because Hibernate can only generate proxies for interfaces, and bootstrap fails with the entity name in the message.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/internal/EntityRepresentationStrategyPojoStandard.java:247
mappedClass,
proxyInterfaces
);
}
private static Set<Class<?>> proxyInterfaces(
PersistentClass bootDescriptor,
Class<?> proxyInterface,
Class<?> mappedClass) {
// HHH-17578 - We need to preserve the order of the interfaces to ensure
// that the most general @Proxy declared interface at the top of a class
// hierarchy will be used first when a HibernateProxy decides what it
// should implement.
final Set<Class<?>> proxyInterfaces = new LinkedHashSet<>();
if ( proxyInterface != null && ! mappedClass.equals( proxyInterface ) ) {
if ( ! proxyInterface.isInterface() ) {
throw new MappingException( "proxy must be either an interface, or the class itself: "
+ bootDescriptor.getEntityName() );
}
proxyInterfaces.add( proxyInterface );
}
if ( mappedClass.isInterface() ) {
proxyInterfaces.add( mappedClass );
}
for ( var subclass : bootDescriptor.getSubclasses() ) {
final var subclassProxy = subclass.getProxyInterface();
final var subclassClass = subclass.getMappedClass();
if ( subclassProxy != null && !subclassClass.equals( subclassProxy ) ) {
if ( !subclassProxy.isInterface() ) {
throw new MappingException( "proxy must be either an interface, or the class itself: "
+ subclass.getEntityName() );
}
proxyInterfaces.add( subclassProxy );View on GitHub (pinned to fad1729dce)
Solutions
- Point @Proxy(proxyClass=...) at an interface the entity implements
- To disable proxying for the entity, use @Proxy(lazy = false) instead of naming a class
- Omit proxyClass entirely when the default (entity-class proxying decision) is fine
- After fixing, rebuild - this fails at SessionFactory creation so tests catch it immediately
Example fix
// before
@Entity
@Proxy(proxyClass = OrderImpl.class) // concrete class -> MappingException
public class OrderImpl implements Order { ... }
// after
@Entity
@Proxy(proxyClass = Order.class) // interface
public class OrderImpl implements Order { ... }
// or disable proxying
@Entity
@Proxy(lazy = false)
public class OrderImpl implements Order { ... } Defensive patterns
Strategy: validation
Validate before calling
// Scan @Proxy declarations at build time
for ( Class<?> c : mappedEntityClasses() ) {
Proxy p = c.getAnnotation(Proxy.class);
if ( p != null && !void.class.equals(p.proxyClass()) && !p.proxyClass().isInterface() && !p.proxyClass().equals(c) ) {
throw new IllegalStateException("@Proxy on " + c + " names a concrete class " + p.proxyClass());
}
} Type guard
static boolean isValidProxyDeclaration(Class<?> entity, Class<?> proxyClass) {
return proxyClass.isInterface() || proxyClass.equals(entity);
} Try / catch
try {
return sessionFactoryBuilder.build();
}
catch ( org.hibernate.mapping.MappingException e ) {
if ( e.getMessage() != null && e.getMessage().startsWith("proxy must be either an interface") ) {
throw new ConfigurationError("Fix @Proxy(proxyClass=...) - must be an interface: " + e.getMessage(), e);
}
throw e;
} Prevention
- Only point @Proxy(proxyClass=...) at interfaces the entity implements
- Use @Proxy(lazy = false) to disable proxying instead of naming a class
- Build the SessionFactory in a CI smoke test so mapping errors surface before deployment
When it happens
Trigger: Specifying @org.hibernate.annotations.Proxy(proxyClass = SomeConcreteClass.class) where that class is a concrete class different from the entity; XML <class ... proxy="com.acme.ConcreteThing"> pointing at a class; accidentally passing the entity's superclass (a class) instead of its interface.
Common situations: Copying @Proxy annotations between hierarchies; intending to disable proxying and mistakenly pointing proxyClass at the impl class of a different type; refactoring an interface into a base class without updating the annotation.
Related errors
- proxy must be either an interface, or the class itself: {ent
- Attribute was not a Map : ${collectionMemberType}
- Unable to create AttributeConverter instance
- Native temporal exclusion column option is not supported by
- CurrentTimestampGeneration requires exactly one column
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/8c9ca3bef7f0030d.
Report an issue: GitHub.