quarkusio/quarkus · error · IllegalStateException
Only a single instance of '${annotation}' is allowed per RES
Error message
Only a single instance of '${annotation}' is allowed per REST Client interface. Offending class is '${class}' What it means
A REST Client interface may declare at most one method annotated with a given context-resolver-style annotation (supplied by RestClientReactiveResolverBuildItem, e.g. `@ClientQueryParam` resolver style handlers). Quarkus generates one class per annotation per interface and throws IllegalStateException when it encounters a second instance for the same interface.
Source
Thrown at extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java:930
}
return result;
}
private Map<String, GeneratedClassResult> populateClientProviderFromAnnotations(
AnnotationToRegisterIntoClientContextBuildItem annotationBuildItem,
Gizmo gizmo,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses, IndexView index) {
var result = new HashMap<String, GeneratedClassResult>();
ClientContextResolverHandler handler = new ClientContextResolverHandler(annotationBuildItem.getAnnotation(),
annotationBuildItem.getExpectedReturnType(), gizmo);
for (AnnotationInstance instance : index.getAnnotations(annotationBuildItem.getAnnotation())) {
GeneratedClassResult classResult = handler.generateContextResolver(instance);
if (classResult == null) {
continue;
}
if (result.containsKey(classResult.interfaceName)) {
throw new IllegalStateException("Only a single instance of '" + annotationBuildItem.getAnnotation()
+ "' is allowed per REST Client interface. Offending class is '" + classResult.interfaceName + "'");
}
result.put(classResult.interfaceName, classResult);
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(classResult.generatedClassName)
.reason(getClass().getName())
.build());
}
return result;
}
private int getAnnotatedPriority(IndexView index, String className, int defaultPriority) {
ClassInfo providerClass = index.getClassByName(DotName.createSimple(className));
int priority = defaultPriority;
if (providerClass == null) {
log.warnv("Unindexed provider class {0}. The priority of the provider will be set to {1}. ", className,
defaultPriority);
} else {
AnnotationInstance priorityAnnoOnProvider = providerClass.declaredAnnotation(ResteasyReactiveDotNames.PRIORITY);View on GitHub (pinned to e1c734241f)
Solutions
- Keep a single method with the annotation on the interface and merge logic
- Remove the duplicate from the parent interface or exclude inheritance
- Move shared behavior into a plain helper method
Example fix
// before
@MyResolver String resolve1(UriInfo uri)
@MyResolver String resolve2(UriInfo uri)
// after
@MyResolver String resolve(UriInfo uri) {
return cond ? resolve1Logic(uri) : resolve2Logic(uri);
} Defensive patterns
Strategy: validation
Validate before calling
// Assert at most one resolver-annotated method per client interface
long count = Arrays.stream(MyClient.class.getMethods())
.filter(m -> m.isAnnotationPresent(MyResolver.class))
.count();
if (count > 1) throw new IllegalStateException("Multiple @MyResolver methods on " + MyClient.class); Prevention
- One annotated resolver method per client interface, period
- Inspect inherited interfaces before adding a resolver
- Use code review checklists for client interface changes
When it happens
Trigger: Two methods annotated with the same resolver annotation (e.g. two `@ClientExceptionMapper`-style generated handlers from a registered annotation build item) on the same interface, including via inheritance.
Common situations: Inheriting a resolver method from a parent interface while also declaring one directly; copy-paste duplication within one interface.
Related errors
- @RegisterClientContextResolver is only supported on static m
- @RegisterClientContextResolver is only supported on static m
- @ClientExceptionMapper is only supported on static methods o
- @ClientRedirectHandler is only supported on static methods o
- Classes used in @SseEventFilter must have a no-args construc
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9043689e7dfd3ab7.
Report an issue: GitHub.