quarkusio/quarkus · critical · RuntimeException

Failed to load generated class %s

Error message

Failed to load generated class %s

What it means

Quarkus OIDC GraphQL integration generated a token-provider/ filter class at build time and the recorder now tries to load it by name through the thread-context classloader. If the class is not visible to the current ClassLoader (deployment vs runtime classloader split, or the class was never generated), a ClassNotFoundException is wrapped in this RuntimeException and startup fails.

Source

Thrown at extensions/oidc-client-graphql/runtime/src/main/java/io/quarkus/oidc/client/graphql/runtime/OidcGraphQLClientIntegrationRecorder.java:35

        GraphQLClientsConfiguration configs = GraphQLClientsConfiguration.getInstance();
        configs.getClients().forEach((graphQLClientKey, value) -> {
            String oidcClient = configKeysToOidcClients.get(graphQLClientKey);
            if (oidcClient == null) {
                oidcClient = defaultOidcClientName;
            }
            Map<String, Uni<String>> dynamicHeaders = configs.getClient(graphQLClientKey).getDynamicHeaders();
            var tokenProviderClass = loadClass(oidcClientToTokenProducerName.get(oidcClient));
            Uni<String> accessTokenProvider = container.<AbstractGraphQLTokenProvider> instance(tokenProviderClass)
                    .get().getAccessToken();
            dynamicHeaders.put("Authorization", accessTokenProvider);
        });
    }

    private static Class<?> loadClass(String className) {
        try {
            return Thread.currentThread().getContextClassLoader().loadClass(className);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Failed to load generated class " + className, e);
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Verify the quarkus-oidc-client-graphql runtime and deployment modules come from the same Quarkus version (mvn dependency:tree).
  2. Ensure the code path runs on a thread whose context classloader is the Quarkus application classloader; wrap custom threads with TCCL set.
  3. Clean rebuild (./mvnw clean install) so the build-time bytecode generation reruns and regenerates the class.
  4. If thrown from your own code, load generated classes via TCCL of the current (Quarkus) thread rather than the recorder's defining classloader.

Example fix

// before
Class<?> clazz = MyClass.class.getClassLoader().loadClass(generatedClassName);
// after
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(generatedClassName);
Defensive patterns

Strategy: try-catch

Validate before calling

try {
    Class.forName(className, false, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
    throw new IllegalStateException("Generated class not on TCCL: " + className, e);
}

Type guard

boolean isLoadable(String name) {
    try { Class.forName(name, false, Thread.currentThread().getContextClassLoader()); return true; }
    catch (ClassNotFoundException e) { return false; }
}

Try / catch

try {
    Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (RuntimeException e) {
    if (e.getCause() instanceof ClassNotFoundException) {
        // fail fast with classloader diagnostics: log TCCL and extension versions
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling OidcGraphQLClientIntegrationRecorder.loadClass with a class name that was not produced by the bytecode generation step, or when the current thread context classloader cannot see the generated class (e.g. wrong TCCL in a custom thread or non-standard deployment).

Common situations: Upgrading Quarkus where the generated class name changed; running the app inside a custom launcher that resets the context classloader; mixing extension versions so the recorder and generator disagree on the class name.

Related errors


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