{"record":{"id":"8401c0deccdcbffa","repo":"quarkusio/quarkus","slug":"duplicate-clientheaderparam-annotation-for-header","errorCode":null,"errorMessage":"Duplicate ClientHeaderParam annotation for header: ${headerName} on ${target}","messagePattern":"Duplicate ClientHeaderParam annotation for header: (.+?) on (.+?)","errorType":"exception","errorClass":"RestClientDefinitionException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java","lineNumber":742,"sourceCode":"     * @param javaMethodField method reference in a static class field\n     * @param methodCreator method for which we put the java.lang.reflect.Method to context (aka this method)\n     * @param invocationBuilder Invocation.Builder in this method\n     */\n    private void addJavaMethodToContext(FieldDescriptor javaMethodField, MethodCreator methodCreator,\n            AssignableResultHandle invocationBuilder) {\n        ResultHandle javaMethod = methodCreator.readStaticField(javaMethodField);\n        ResultHandle javaMethodAsObject = methodCreator.checkCast(javaMethod, Object.class);\n        methodCreator.assign(invocationBuilder,\n                methodCreator.invokeInterfaceMethod(INVOCATION_BUILDER_PROPERTY_METHOD, invocationBuilder,\n                        methodCreator.load(INVOKED_METHOD_PROP), javaMethodAsObject));\n    }\n\n    private void putAllHeaderAnnotations(Map<String, ParamData> headerMap, ClassInfo interfaceClass,\n            AnnotationInstance[] annotations) {\n        for (AnnotationInstance annotation : annotations) {\n            String headerName = annotation.value(\"name\").asString();\n            if (headerMap.put(headerName, new ParamData(annotation, interfaceClass)) != null) {\n                throw new RestClientDefinitionException(\"Duplicate ClientHeaderParam annotation for header: \" + headerName +\n                        \" on \" + annotation.target());\n            }\n        }\n    }\n\n    // fillHeaders takes `MultivaluedMap<String, String>` as param and modifies it\n    private void addHeaderParam(MethodInfo declaringMethod, MethodCreator fillHeadersCreator,\n            ParamData paramData,\n            BuildProducer<GeneratedClassBuildItem> generatedClasses,\n            String fillerClassName,\n            IndexView index) {\n\n        AnnotationInstance annotation = paramData.annotation;\n        ClassInfo declaringClass = paramData.definingClass;\n\n        String headerName = annotation.value(\"name\").asString();\n\n        String[] values = annotation.value().asStringArray();","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java#L724-L760","documentation":"Two @ClientHeaderParam annotations for the same header name were found on the client interface (e.g. at both the class and method level, or in repeated containers). Since only one value can be sent per header, the enricher throws during putAllHeaderAnnotations instead of silently choosing one.","triggerScenarios":"Applying @ClientHeaderParam(name=\"Authorization\") on both the interface and a method, or repeating the annotation for the same name; the map put returns a previous entry and the build fails.","commonSituations":"Copy-pasting method-level annotations after a class-level one already defines the header; inheritance from a base interface re-declaring the same header.","solutions":["Remove the duplicate @ClientHeaderParam for that header name","Keep a single definition at the class level if it applies everywhere","Rename the header if two distinct headers were intended"],"exampleFix":"// before\n@ClientHeaderParam(name = \"Auth\", value = \"a\")\ninterface Client { @ClientHeaderParam(name = \"Auth\", value = \"b\") String get(); }\n// after\n@ClientHeaderParam(name = \"Auth\", value = \"a\")\ninterface Client { String get(); }","handlingStrategy":"validation","validationCode":"// Collect header names at startup to detect duplicates\nMap<String,Integer> seen = new HashMap<>();\nfor (ClientHeaderParam a : iface.getAnnotationsByType(ClientHeaderParam.class))\n    seen.merge(a.name(), 1, Integer::sum);\nList<String> dupes = seen.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).toList();\nif (!dupes.isEmpty()) throw new IllegalStateException(\"Duplicate headers: \" + dupes);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Define each header once, at class level when it applies everywhere","Search the interface (and parents) before adding @ClientHeaderParam","Avoid copy-pasting method-level annotations that repeat class-level headers"],"tags":["rest-client","duplicate-annotation","microprofile"],"backgroundTag":"duplicate-annotation-conflict","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"}