{"record":{"id":"4e1568823075fdbe","repo":"quarkusio/quarkus","slug":"only-a-single-instance-of-clientredirecthandler","errorCode":null,"errorMessage":"Only a single instance of '@ClientRedirectHandler' with the same priority is allowed per REST Client interface. Offending class is '${class}'","messagePattern":"Only a single instance of '@ClientRedirectHandler' with the same priority 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":903,"sourceCode":"        }\n        return result;\n    }\n\n    private Map<String, GeneratedClassResult> populateClientRedirectHandlerFromAnnotations(\n            Gizmo gizmo,\n            BuildProducer<ReflectiveClassBuildItem> reflectiveClasses, IndexView index) {\n\n        var result = new HashMap<String, GeneratedClassResult>();\n        ClientRedirectHandler clientHandler = new ClientRedirectHandler(gizmo);\n        for (AnnotationInstance instance : index.getAnnotations(CLIENT_REDIRECT_HANDLER)) {\n            GeneratedClassResult classResult = clientHandler.generateResponseExceptionMapper(instance);\n            if (classResult == null) {\n                continue;\n            }\n\n            GeneratedClassResult existing = result.get(classResult.interfaceName);\n            if (existing != null && existing.priority == classResult.priority) {\n                throw new IllegalStateException(\"Only a single instance of '\" + CLIENT_REDIRECT_HANDLER\n                        + \"' with the same priority is allowed per REST Client interface. \"\n                        + \"Offending class is '\" + classResult.interfaceName + \"'\");\n            } else if (existing == null || existing.priority < classResult.priority) {\n                result.put(classResult.interfaceName, classResult);\n                reflectiveClasses.produce(ReflectiveClassBuildItem.builder(classResult.generatedClassName)\n                        .reason(getClass().getName())\n                        .build());\n            }\n        }\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>();","sourceCodeStart":885,"sourceCodeEnd":921,"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#L885-L921","documentation":"A REST Client interface may not declare two `@ClientRedirectHandler` methods with the same priority. Quarkus keeps a priority-ordered map of generated redirect handlers per interface and throws IllegalStateException on a priority collision, since ordering would be ambiguous.","triggerScenarios":"Two `@ClientRedirectHandler` static methods on the same client interface whose `priority()` attribute values are identical.","commonSituations":"Copy-pasting a redirect handler and forgetting to change the priority; two handlers inherited from different parent interfaces that happen to share a priority.","solutions":["Change the `priority` attribute of one handler so values are unique","Merge the two handlers into one method with the desired logic","Remove the redundant handler"],"exampleFix":"// before\n@ClientRedirectHandler(priority = 100) Response h1(...)\n@ClientRedirectHandler(priority = 100) Response h2(...)\n// after\n@ClientRedirectHandler(priority = 100) Response h1(...)\n@ClientRedirectHandler(priority = 200) Response h2(...)","handlingStrategy":"validation","validationCode":"// Ensure priorities are unique per interface\nMap<Integer, Long> byPriority = Arrays.stream(MyClient.class.getMethods())\n    .filter(m -> m.isAnnotationPresent(ClientRedirectHandler.class))\n    .map(m -> m.getAnnotation(ClientRedirectHandler.class).priority())\n    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));\nif (byPriority.values().stream().anyMatch(c -> c > 1)) throw new IllegalStateException(\"Duplicate handler priority\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Change priority whenever copy-pasting a @ClientRedirectHandler","Document priority conventions per project to avoid collisions","Check parent interfaces for handlers with the same priority"],"tags":["rest-client","redirect-handler","annotation-processing","build-time"],"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"}