quarkusio/quarkus · warning · HibernateException

Could not lookup a pre-generated proxy class definition for

Error message

Could not lookup a pre-generated proxy class definition for entity '%s' (class='%s'): %s

What it means

Quarkus generates lazy-load proxies for entities at build time; QuarkusProxyFactory.postInstantiate() looks up the pre-generated proxy definition when a persistence unit starts. If the entity's class cannot be proxied (it is final, or has a final/overridden-incompatible method), a HibernateException is thrown with a reason explaining why. This variant is intended to be caught and logged as a warning by Hibernate ORM.

Source

Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/customized/QuarkusProxyFactory.java:72

        this.interfaces = toArray(interfaces);
        this.getIdentifierMethod = getIdentifierMethod;
        this.setIdentifierMethod = setIdentifierMethod;
        this.componentIdType = componentIdType;
        ProxyDefinitions.ProxyClassDetailsHolder detailsHolder = proxyClassDefinitions.getProxyForClass(persistentClass);
        if (detailsHolder == null) {
            String reason = null;
            // Some Envers entity classes are final, e.g. org.hibernate.envers.DefaultRevisionEntity
            // There's nothing users can do about it, so let's not fail in those cases.
            if (persistentClass.getName().startsWith("org.hibernate.")) {
                reason = "this is a limitation of this particular Hibernate class.";
            }
            // See also ProxyBuildingHelper#isProxiable
            else if (Modifier.isFinal(persistentClass.getModifiers())) {
                reason = "this class is final. Your application might perform better if this class was non-final.";
            }
            if (reason != null) {
                // This is caught and logged as a warning by Hibernate ORM.
                throw new HibernateException(String.format(Locale.ROOT,
                        "Could not lookup a pre-generated proxy class definition for entity '%s' (class='%s'): %s", entityName,
                        persistentClass.getCanonicalName(), reason));
            } else {
                // This will fail bootstrap.
                throw new IllegalStateException(String.format(Locale.ROOT,
                        "Could not lookup a pre-generated proxy class definition for entity '%s' (class='%s')." +
                                "This should not happen, please open an issue at https://github.com/quarkusio/quarkus/issues",
                        entityName, persistentClass.getCanonicalName()));
            }
        }
        this.overridesEquals = detailsHolder.isOverridesEquals();
        this.constructor = detailsHolder.getConstructor();

    }

    private static Class<?>[] toArray(Set<Class<?>> interfaces) {
        if (interfaces == null) {
            return ArrayHelper.EMPTY_CLASS_ARRAY;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the entity class non-final and keep its no-arg constructor and property getters non-final so Hibernate can generate lazy proxies.
  2. If finality is intentional and lazy loading is not needed, disable proxying for the entity (lazy="no-proxy"/@Lazy(false)-style options or lazy=false mappings).
  3. Check build logs for why the proxy class wasn't pre-generated for this entity and fix the modeling issue.
  4. Ensure the entity type is compiled with a public/protected no-arg constructor as required by JPA.

Example fix

// before
public final class Order { ... }

// after
public class Order { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Validate entity proxyability before bootstrapping
static <T> String checkProxiable(Class<T> entity) {
    if (java.lang.reflect.Modifier.isFinal(entity.getModifiers())) {
        return "entity class is final";
    }
    if (java.lang.reflect.Modifier.isFinal(entity.getConstructors()[0].getModifiers())) {
        return "constructor is final";
    }
    return null;
}

Type guard

static boolean isProxyable(Class<?> c) {
    return !java.lang.reflect.Modifier.isFinal(c.getModifiers())
        && !c.isRecord()
        && java.lang.reflect.Modifier.isPublic(c.getModifiers());
}

Try / catch

try {
    emf = Persistence.createEntityManagerFactory("pu");
} catch (HibernateException e) {
    if (e.getMessage() != null && e.getMessage().contains("pre-generated proxy class definition")) {
        log.warn("Entity not proxiable: " + e.getMessage() + " — make it non-final or disable lazy proxying");
    }
    throw e;
}

Prevention

When it happens

Trigger: Bootstrapping a persistence unit containing an entity class that is final, or whose key methods are final, so no pre-generated proxy definition exists; postInstantiate then builds the reason string ('this class is final...') and throws.

Common situations: Declaring an @Entity class or its getId() method as final; upgrading Quarkus and adding an entity that violates proxying rules; classes enhanced/obfuscated in ways preventing proxy generation.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/544cf575008818d6. Report an issue: GitHub.