{"record":{"id":"9043689e7dfd3ab7","repo":"quarkusio/quarkus","slug":"only-a-single-instance-of-annotation-is-allow","errorCode":null,"errorMessage":"Only a single instance of '${annotation}' is allowed per REST Client interface. Offending class is '${class}'","messagePattern":"Only a single instance of '(.+?)' is allowed per REST Client interface\\. Offending class is '(.+?)'","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java","lineNumber":930,"sourceCode":"        }\n        return result;\n    }\n\n    private Map<String, GeneratedClassResult> populateClientProviderFromAnnotations(\n            AnnotationToRegisterIntoClientContextBuildItem annotationBuildItem,\n            Gizmo gizmo,\n            BuildProducer<ReflectiveClassBuildItem> reflectiveClasses, IndexView index) {\n\n        var result = new HashMap<String, GeneratedClassResult>();\n        ClientContextResolverHandler handler = new ClientContextResolverHandler(annotationBuildItem.getAnnotation(),\n                annotationBuildItem.getExpectedReturnType(), gizmo);\n        for (AnnotationInstance instance : index.getAnnotations(annotationBuildItem.getAnnotation())) {\n            GeneratedClassResult classResult = handler.generateContextResolver(instance);\n            if (classResult == null) {\n                continue;\n            }\n            if (result.containsKey(classResult.interfaceName)) {\n                throw new IllegalStateException(\"Only a single instance of '\" + annotationBuildItem.getAnnotation()\n                        + \"' is allowed per REST Client interface. Offending class is '\" + classResult.interfaceName + \"'\");\n            }\n            result.put(classResult.interfaceName, classResult);\n            reflectiveClasses.produce(ReflectiveClassBuildItem.builder(classResult.generatedClassName)\n                    .reason(getClass().getName())\n                    .build());\n        }\n        return result;\n    }\n\n    private int getAnnotatedPriority(IndexView index, String className, int defaultPriority) {\n        ClassInfo providerClass = index.getClassByName(DotName.createSimple(className));\n        int priority = defaultPriority;\n        if (providerClass == null) {\n            log.warnv(\"Unindexed provider class {0}. The priority of the provider will be set to {1}. \", className,\n                    defaultPriority);\n        } else {\n            AnnotationInstance priorityAnnoOnProvider = providerClass.declaredAnnotation(ResteasyReactiveDotNames.PRIORITY);","sourceCodeStart":912,"sourceCodeEnd":948,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java#L912-L948","documentation":"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.","triggerScenarios":"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.","commonSituations":"Inheriting a resolver method from a parent interface while also declaring one directly; copy-paste duplication within one interface.","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"],"exampleFix":"// before\n@MyResolver String resolve1(UriInfo uri)\n@MyResolver String resolve2(UriInfo uri)\n// after\n@MyResolver String resolve(UriInfo uri) {\n    return cond ? resolve1Logic(uri) : resolve2Logic(uri);\n}","handlingStrategy":"validation","validationCode":"// Assert at most one resolver-annotated method per client interface\nlong count = Arrays.stream(MyClient.class.getMethods())\n    .filter(m -> m.isAnnotationPresent(MyResolver.class))\n    .count();\nif (count > 1) throw new IllegalStateException(\"Multiple @MyResolver methods on \" + MyClient.class);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One annotated resolver method per client interface, period","Inspect inherited interfaces before adding a resolver","Use code review checklists for client interface changes"],"tags":["rest-client","annotation-processing","build-time","duplicate"],"backgroundTag":"duplicate-annotation-declaration","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}