quarkusio/quarkus · error · RuntimeException

Unable to handle class: ${applicationClass}

Error message

Unable to handle class: ${applicationClass}

What it means

getAllowedClasses in ResteasyServerCommonProcessor loads the user's Application class via reflection (Class.forName, newInstance or getMethod calls) at build time to invoke getClasses()/getSingletons(). Any failure while loading, instantiating, or invoking it — ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, or InvocationTargetException — is wrapped in this RuntimeException naming the offending class.

Source

Thrown at extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java:1115

        String applicationClass = jakartaRestApplicationClass.name().toString();
        try {
            Class<?> appClass = Thread.currentThread().getContextClassLoader().loadClass(applicationClass);
            application = (Application) appClass.getConstructor().newInstance();
            Set<Class<?>> classes = application.getClasses();
            if (!classes.isEmpty()) {
                for (Class<?> klass : classes) {
                    allowedClasses.add(klass.getName());
                }
            }
            classes = application.getSingletons().stream().map(Object::getClass).collect(Collectors.toSet());
            if (!classes.isEmpty()) {
                for (Class<?> klass : classes) {
                    allowedClasses.add(klass.getName());
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException
                | InvocationTargetException e) {
            throw new RuntimeException("Unable to handle class: " + applicationClass, e);
        }
        return allowedClasses;
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Read the wrapped cause (the RuntimeException's getCause()) to see the underlying exception thrown while loading/invoking the Application class.
  2. Ensure the Application class has a public no-arg constructor that performs no side-effecting/CDI-dependent initialization.
  3. Make every type referenced in getClasses()/getSingletons() available on the classpath and keep the methods side-effect free.
  4. As a workaround, drop getClasses()/getSingletons() and let Quarkus discover @Path/@Provider classes automatically.

Example fix

// before
public class MyApp extends Application {
    private static final Set<Class<?>> CLASSES = buildFromDb(); // throws at build time
    @Override public Set<Class<?>> getClasses() { return CLASSES; }
}

// after
public class MyApp extends Application {
    @Override public Set<Class<?>> getClasses() { return Set.of(MyResource.class); }
}
Defensive patterns

Strategy: try-catch

Validate before calling

static void assertApplicationInstantiable(String appClassName) {
    try {
        Class<?> c = Class.forName(appClassName);
        c.getDeclaredConstructor().newInstance();
    } catch (ReflectiveOperationException e) {
        throw new IllegalStateException("Application class cannot be loaded/instantiated at build time: " + appClassName, e);
    }
}

Type guard

static boolean isBuildTimeInstantiable(Class<?> c) {
    try { c.getDeclaredConstructor().newInstance(); return true; }
    catch (ReflectiveOperationException | RuntimeException e) { return false; }
}

Try / catch

// Thrown during Quarkus augmentation; inspect the wrapped cause to diagnose:
try {
    Quarkus.bootstrap(...); // or run quarkusDev
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unable to handle class:")) {
        log.error("Root cause while loading Application class:", e.getCause());
    }
}

Prevention

When it happens

Trigger: Application class that: cannot be loaded (missing dependency of a referenced type), has no accessible no-arg constructor, throws an exception inside its constructor or getClasses()/getSingletons(), or references classes not visible to the deployment classloader.

Common situations: Application's constructor/getClasses throws NPE due to uninitialized static state; Application references a class from a library not on the deployment classpath; a private or missing no-arg constructor.

Related errors


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