{"record":{"id":"6ce5d3d90b6915cc","repo":"quarkusio/quarkus","slug":"io-quarkus-oidc-client-oidcclientfilter-annotation","errorCode":null,"errorMessage":"io.quarkus.oidc.client.OidcClientFilter annotation can be applied either on class %s or its methods","messagePattern":"io\\.quarkus\\.oidc\\.client\\.OidcClientFilter annotation can be applied either on class (.+?) or its methods","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/oidc-client/deployment/src/main/java/io/quarkus/oidc/client/deployment/OidcClientFilterDeploymentHelper.java","lineNumber":251,"sourceCode":"                                .filter(ai -> ai.target().kind() == AnnotationTarget.Kind.CLASS)\n                                .map(ai -> ai.target().asClass())\n                                .toList());\n                        result.addAll(index\n                                .getAnnotations(registerProvidersClass).stream()\n                                .filter(ai -> ai.value() != null)\n                                .filter(ai -> registersDeclaringClass(ai, declaringClassName))\n                                .filter(ai -> ai.target().kind() == AnnotationTarget.Kind.CLASS)\n                                .map(ai -> ai.target().asClass())\n                                .toList());\n                    }\n                }\n            }\n        }\n        return result;\n    }\n\n    private static void throwBothMethodAndClassAnnotated(AnnotationInstance instance) {\n        throw new RuntimeException(OidcClientFilter.class.getName() + \" annotation can be applied either on class \"\n                + getTargetRestClient(instance) + \" or its methods\");\n    }\n\n    private static boolean registersDeclaringClass(AnnotationInstance ai, DotName declaringClassName) {\n        return Arrays.stream(ai.value().asNestedArray())\n                .anyMatch(nestedAi -> nestedAi.value().asClass().name().equals(declaringClassName));\n    }\n}\n","sourceCodeStart":233,"sourceCodeEnd":260,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc-client/deployment/src/main/java/io/quarkus/oidc/client/deployment/OidcClientFilterDeploymentHelper.java#L233-L260","documentation":"During OIDC client filter build-step processing, a REST client interface was found where the @OidcClientFilter annotation appears both on the class and on at least one of its methods. Quarkus cannot decide unambiguously whether to register the filter per class or per method, so the build fails with this RuntimeException.","triggerScenarios":"A REST client interface annotated with @OidcClientFilter at class level AND with @OidcClientFilter on one of its methods, encountered while getOrCreateNamedTokensProducerFor processes annotation instances.","commonSituations":"Copy-paste adding the annotation to both the interface and an individual method; combining a global class-level filter with an attempt to customize a single method.","solutions":["Remove @OidcClientFilter from the method(s) and keep it only on the class to apply to all methods.","Remove @OidcClientFilter from the class and keep it only on the specific method(s) that need it.","Split the REST client into two interfaces: one class-annotated and one method-annotated, if both behaviors are genuinely needed."],"exampleFix":"// before\n@OidcClientFilter\npublic interface MyClient {\n    @OidcClientFilter\n    @GET String get();\n}\n\n// after\n@OidcClientFilter\npublic interface MyClient {\n    @GET String get();\n}","handlingStrategy":"validation","validationCode":"boolean classAnnotated = Arrays.stream(MyClient.class.getAnnotations()).anyMatch(a -> a instanceof OidcClientFilter);\nboolean methodAnnotated = Arrays.stream(MyClient.class.getMethods()).anyMatch(m -> m.isAnnotationPresent(OidcClientFilter.class));\nif (classAnnotated && methodAnnotated) throw new IllegalStateException(\"@OidcClientFilter on both class and method\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one annotation level: class for all methods, method-level for selective use.","Review REST client interfaces after copy-paste edits.","Run a build-step/architectural test that scans client interfaces for duplicate annotation targets."],"tags":["oidc-client","annotation","rest-client","build-time"],"backgroundTag":"duplicate-annotation-target","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"}