{"record":{"id":"8ea126c74d108cf5","repo":"quarkusio/quarkus","slug":"security-annotations-annotations-cannot-be-app","errorCode":null,"errorMessage":"Security annotations '<annotations>' cannot be applied on the '<method>' method, please move the annotations to the class-level instead","messagePattern":"Security annotations '<annotations>' cannot be applied on the '<method>' method, please move the annotations to the class-level instead","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java","lineNumber":892,"sourceCode":"\n                        for (MethodInfo method : interceptedClass.methods()) {\n                            if (hasProperEndpointModifiers(method)) {\n                                // avoid situation when resource method is annotated with @Basic, class is annotated\n                                // with @Bearer, and we apply the @Bearer annotation\n                                boolean interceptorBindingNotAppliedOnMethodLevel = !cache.containsKey(method)\n                                        || !cache.get(method).contains(interceptorBinding);\n\n                                if (interceptorBindingNotAppliedOnMethodLevel) {\n                                    addInterceptedEndpoint(method, annotation, annotationBinding,\n                                            bindingValueToInterceptedMethods, interceptorBinding);\n                                }\n                            }\n                        }\n                    } else {\n                        MethodInfo mi = annotation.target().asMethod();\n\n                        if (hasClassLevelSecurity.test(mi.declaringClass())) {\n                            throw new RuntimeException(\n                                    (\"Security annotations '%s' cannot be applied on the '%s' method, \"\n                                            + \"please move the annotations to the class-level instead\").formatted(\n                                                    Arrays.toString(Arrays.stream(interceptorBinding.getAnnotationBindings())\n                                                            .toArray()),\n                                                    toTargetName(mi)));\n                        } else {\n                            // only allow to combine interceptor bindings on endpoints if we explicitly support it\n                            var appliedBindings = cache.computeIfAbsent(mi, a -> new ArrayList<>());\n                            if (appliedBindings.contains(interceptorBinding)) {\n                                if (!interceptorBinding.allowToRepeatThisInterceptorBinding()) {\n                                    throw new RuntimeException(\n                                            \"Only one of the '%s' annotations can be applied on the '%s' method\".formatted(\n                                                    Arrays.toString(interceptorBinding.getAnnotationBindings()),\n                                                    toTargetName(mi)));\n                                }\n                            } else {\n                                appliedBindings.add(interceptorBinding);\n                            }","sourceCodeStart":874,"sourceCodeEnd":910,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java#L874-L910","documentation":"When an endpoint class already has a class-level security annotation (e.g. @Basic), placing a method-level security annotation on one of its methods is rejected: the class-level mechanism governs and a per-method override of that category is not allowed. The build fails and points at the offending method, advising to consolidate annotations at class level.","triggerScenarios":"Annotating a method with an auth mechanism annotation (e.g. @Form) inside a class already annotated with a class-level security annotation (e.g. @Basic).","commonSituations":"Trying to 'override' the class mechanism for one endpoint; adding a new method with a copied annotation from another class; incremental security tightening that collided with existing class-level config.","solutions":["Remove the method-level security annotation and rely on the class-level one","Change the class-level annotation to the mechanism you actually need","Remove the class-level annotation and annotate each method individually instead"],"exampleFix":"// before\n@Basic\npublic class UserResource {\n    @Form\n    @GET\n    public String get() { ... }\n}\n// after\n@Basic\npublic class UserResource {\n    @GET\n    public String get() { ... }\n}","handlingStrategy":"validation","validationCode":"if (Resource.class.isAnnotationPresent(Basic.class)\n    && Arrays.stream(Resource.class.getDeclaredMethods())\n        .anyMatch(m -> m.isAnnotationPresent(Form.class))) {\n    throw new IllegalStateException(\"Method-level security annotation conflicts with class-level one\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never mix class-level and method-level mechanism annotations on the same resource","Consolidate security annotations at class level when the whole class shares a mechanism","Use per-method annotations only when the class has none"],"tags":["quarkus","build-time","security","annotation"],"backgroundTag":"conflicting-security-annotations","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"}