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
- Replace the lambda with an explicit class that implements ContextResolver<YourMediaType>, stating the generic type in the class declaration.
- 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.
- Register a named class instance: client.register(new MyContextResolver()).
- 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
- Always implement ContextResolver as a named class with an explicit generic type parameter.
- Never use lambdas or method references for JAX-RS providers that rely on generic type introspection.
- Add a code-review check for register(...) calls receiving lambdas.
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
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Unsupported type '${jaxRSAnnotationOfParam.name()}' used as
- Resource classes that use field injection for REST parameter
- Resource classes that use field injection for REST parameter
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/8ec741dc89eafe26.
Report an issue: GitHub.