quarkusio/quarkus · error · IllegalStateException

@RegisterClientContextResolver is only supported on static m

Error message

@RegisterClientContextResolver is only supported on static methods of REST Client interfaces that return '${expectedReturnType}'. Offending instance is '${className}#${methodName}'

What it means

@RegisterClientContextResolver annotates a static method inside a REST client interface that supplies custom context resolvers. Quarkus generates the wiring at build time and requires the annotated method's return type to be assignable to the resolver type expected by the annotated parameter. This IllegalStateException fires when the method returns a type incompatible with the expected resolver return type.

Source

Thrown at extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/ClientContextResolverHandler.java:99

    GeneratedClassResult generateContextResolver(AnnotationInstance instance) {
        if (!annotation.equals(instance.name())) {
            throw new IllegalArgumentException(
                    "'clientContextResolverInstance' must be an instance of " + annotation);
        }
        MethodInfo targetMethod = findTargetMethod(instance);
        if (targetMethod == null) {
            return null;
        }

        int priority = Priorities.USER;
        AnnotationValue priorityAnnotationValue = instance.value("priority");
        if (priorityAnnotationValue != null) {
            priority = priorityAnnotationValue.asInt();
        }

        Class<?> returnTypeClassName = lookupReturnClass(targetMethod);
        if (!expectedReturnType.isAssignableFrom(returnTypeClassName)) {
            throw new IllegalStateException(annotation
                    + " is only supported on static methods of REST Client interfaces that return '" + expectedReturnType + "'."
                    + " Offending instance is '" + targetMethod.declaringClass().name().toString() + "#"
                    + targetMethod.name() + "'");
        }

        ClassInfo restClientInterfaceClassInfo = targetMethod.declaringClass();
        String generatedClassName = getGeneratedClassName(targetMethod);
        final MethodInfo target = targetMethod;
        gizmo.class_(generatedClassName, cc -> {
            cc.implements_(GenericType.ofClass(ResteasyReactiveContextResolver.class,
                    TypeArgument.of(returnTypeClassName)));
            cc.defaultConstructor();
            cc.method("getContext", mc -> {
                mc.returning(Object.class);
                ParamVar typeParam = mc.parameter("type", Class.class);
                mc.body(bc -> {
                    LinkedHashMap<String, Expr> targetMethodParams = new LinkedHashMap<>();
                    for (Type paramType : target.parameterTypes()) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the annotated static method return exactly the type expected (assignable to the expected return type shown in the message)
  2. Ensure the method is static and declared inside the REST client interface
  3. If you intended a different resolver kind, use the matching annotation/target type for your return type
  4. Check the generated message for '${className}#${methodName}' to locate the offending method quickly

Example fix

// before
@RegisterClientContextResolver
static String myResolver() { return "x"; } // wrong return type
// after
@RegisterClientContextResolver
static MyContextType myResolver() { return new MyContextType(); }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check before build-time processing (conceptual):
// static method, return type assignable to expected resolver type
static void validate(MethodInfo m, DotName expected) {
    if (!TypeKind.isAssignableFrom(expected, m.returnType().name()))
        throw new IllegalStateException(m.name() + " must return " + expected);
}

Try / catch

try {
    classResult.process();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("RegisterClientContextResolver")) {
        // point developer at className#methodName in message
    }
    throw e;
}

Prevention

When it happens

Trigger: Annotating a static method in a REST client interface whose return type is not assignable to the expected return type (declared via the annotation target/parameter); e.g. the method returns String while a Response-based context resolver is expected.

Common situations: Copy-pasting a context resolver method from another client; changing the resolver type but forgetting to change the method return type; using a non-static or wrong-signature helper method.

Related errors


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