quarkusio/quarkus · error · IllegalArgumentException

Registering a ContextResolver via a lambda is not supported

Error message

Registering a ContextResolver via a lambda is not supported

What it means

RESTEasy Reactive's client configuration stores ContextResolver instances keyed by the media type they handle, discovered via generic type introspection. Java lambdas are synthetic classes whose generic parameters cannot be reliably resolved, so the resolver would be keyed to Object.class and match everything incorrectly. The library detects this situation (key resolved to Object.class on a synthetic class) and refuses to register it rather than misbehaving at runtime.

Source

Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/ConfigurationImpl.java:326

                resourceWriters.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class,
                        resourceWriter);
            }
        }
        if (component instanceof RxInvokerProvider) {
            added = true;
            Class<?> componentClass = component.getClass();
            Type[] args = Types.findParameterizedTypes(componentClass, RxInvokerProvider.class);
            rxInvokerProviders.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class,
                    (RxInvokerProvider<?>) component);
        }
        if (component instanceof ContextResolver) {
            added = true;
            Class<?> componentClass = component.getClass();
            Type[] args = Types.findParameterizedTypes(componentClass, ContextResolver.class);
            Class<?> key = args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class;
            // in this case we are almost certain a lambda was used so we should fail
            if ((key == Object.class) && component.getClass().isSynthetic()) {
                throw new IllegalArgumentException("Registering a ContextResolver via a lambda is not supported");
            }
            int effectivePriority = priority != null ? priority : determinePriority(component);
            contextResolvers.computeIfAbsent(key, k -> new MultivaluedTreeMap<>())
                    .add(effectivePriority, (ContextResolver<?>) component);
        }
        if (added) {
            allInstances.put(component.getClass(), component);

            Map<Class<?>, Integer> contracts = new HashMap<>();
            for (Class<?> contractableClass : contractableClasses) {
                contracts.put(contractableClass, priority);
            }
            this.contracts.put(component.getClass(), contracts);
        }
    }

    public void register(Object component, Class<?>[] contracts) {
        if (contracts == null || contracts.length == 0) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Replace the lambda with an explicit class that implements ContextResolver<YourMediaType>, stating the generic type in the class declaration.
  2. Use an anonymous inner class instead of a lambda: new ContextResolver<JacksonConfig>() { ... } retains enough type information in some setups, but a named class is safest.
  3. Register a named class instance: client.register(new MyContextResolver()).
  4. If an explicit priority/type is needed, pass it via register(component, priority) — but the lambda itself still cannot be used for ContextResolver.

Example fix

// before
client.register((ContextResolver<Object>) type -> myResolver.getContext(type));

// after
public class MyContextResolver implements ContextResolver<ContextResolver<?>> {
    @Override
    public Object getContext(Class<?> type) { return myResolver.getContext(type); }
}
client.register(new MyContextResolver());
Defensive patterns

Strategy: validation

Validate before calling

if (component instanceof ContextResolver && component.getClass().isSynthetic()) {
    throw new IllegalArgumentException("Use a named ContextResolver class, not a lambda");
}
client.register(component);

Type guard

boolean isRegisterableResolver(Object c) {
    return !(c instanceof ContextResolver) || !c.getClass().isSynthetic();
}

Try / catch

try {
    client.register(resolver);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("ContextResolver via a lambda")) {
        client.register(new NamedContextResolver());
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling clientBuilder.register((ContextResolver<Object>) type -> null) or similar register(...) invocation where the component is a lambda implementing ContextResolver, since Types.findParameterizedTypes cannot extract the media type argument from the synthetic lambda class.

Common situations: Registering context resolvers inline as lambdas when configuring a REST client or JAX-RS client; code that worked with an anonymous class fails after refactoring to a lambda; users unaware that generic type information is erased for lambdas.

Related errors


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