{"record":{"id":"768abe6afa3aec3c","repo":"quarkusio/quarkus","slug":"found-method-annotated-with-the-authorizationpoli","errorCode":null,"errorMessage":"Found method annotated with the @AuthorizationPolicy annotation that is not an endpoint: <class>#<method>","messagePattern":"Found method annotated with the @AuthorizationPolicy annotation that is not an endpoint: <class>#<method>","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java","lineNumber":743,"sourceCode":"    @Record(ExecutionTime.STATIC_INIT)\n    @BuildStep(onlyIf = AlwaysPropagateSecurityIdentity.class)\n    IgnoredContextLocalDataKeysBuildItem dontPropagateSecurityIdentityToDuplicateContext(HttpSecurityRecorder recorder) {\n        return new IgnoredContextLocalDataKeysBuildItem(recorder.getSecurityIdentityContextKeySupplier());\n    }\n\n    private static Stream<MethodInfo> getPolicyTargetEndpointCandidates(AnnotationTarget target,\n            SecurityTransformer securityTransformer) {\n        if (target.kind() == AnnotationTarget.Kind.METHOD) {\n            var method = target.asMethod();\n            if (!hasProperEndpointModifiers(method)) {\n                if (method.isSynthetic() && method.name().endsWith(KOTLIN_SUSPEND_IMPL_SUFFIX)) {\n                    // ATM there are 2 methods for Kotlin endpoint like this:\n                    // @AuthorizationPolicy(name = \"suspended\")\n                    // suspend fun sayHi() = \"Hi\"\n                    // the synthetic method doesn't need to be secured, but it keeps security annotations\n                    return Stream.empty();\n                }\n                throw new RuntimeException(\"\"\"\n                        Found method annotated with the @AuthorizationPolicy annotation that is not an endpoint: %s#%s\n                        \"\"\".formatted(method.declaringClass().name().toString(), method.name()));\n            }\n            return Stream.of(method);\n        }\n        return target.asClass().methods().stream()\n                .filter(HttpSecurityProcessor::hasProperEndpointModifiers)\n                .filter(mi -> !securityTransformer.hasSecurityAnnotation(mi));\n    }\n\n    private static void validateAuthMechanismAnnotationUsage(Capabilities capabilities,\n            VertxHttpBuildTimeConfig buildTimeConfig,\n            DotName[] annotationNames) {\n        if (buildTimeConfig.auth().proactive()\n                || (capabilities.isMissing(Capability.RESTEASY_REACTIVE) && capabilities.isMissing(Capability.RESTEASY)\n                        && capabilities.isMissing(Capability.WEBSOCKETS_NEXT))) {\n            throw new ConfigurationException(\"Annotations '\" + Arrays.toString(annotationNames) + \"' can only be used when\"\n                    + \" proactive authentication is disabled and either Quarkus REST, RESTEasy Classic or WebSockets Next\"","sourceCodeStart":725,"sourceCodeEnd":761,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java#L725-L761","documentation":"@AuthorizationPolicy placed on a method is only meaningful when that method is a JAX-RS/Quarkus REST endpoint that can be secured with the named policy. When the annotated method is not an endpoint, Quarkus cannot map the policy to any HTTP route and fails the build, reporting the class and method. Note that synthetic Kotlin suspend companion methods are skipped rather than rejected.","triggerScenarios":"Placing @AuthorizationPolicy on a regular (non-endpoint) method — one not exposed via RESTEasy/Quarkus REST — or on a method the annotation scanner cannot resolve to an endpoint candidate.","commonSituations":"Annotating a service-layer method expecting security to apply; Kotlin endpoints where the real endpoint is the synthetic method; annotating a private/helper method by mistake.","solutions":["Move @AuthorizationPolicy to an actual JAX-RS resource method or to the resource class","If it's a Kotlin suspend endpoint, ensure the annotation targets the endpoint method per the documented pattern","Remove the annotation if the method is not an HTTP endpoint and secure it another way"],"exampleFix":"// before\n@AuthorizationPolicy(name = \"suspended\")\npublic void helperMethod() { ... }\n// after\n@Path(\"/admin\")\npublic class AdminResource {\n    @GET\n    @AuthorizationPolicy(name = \"admin-policy\")\n    public String admin() { ... }\n}","handlingStrategy":"validation","validationCode":"Method m = targetMethod;\nif (m.isAnnotationPresent(AuthorizationPolicy.class) &&\n    !Arrays.stream(m.getAnnotations()).anyMatch(a -> a.annotationType().isAnnotationPresent(Path.class))) {\n    throw new IllegalStateException(\"@AuthorizationPolicy only valid on JAX-RS endpoint methods\");\n}","typeGuard":"boolean isEndpointMethod(Method m) {\n    return m.isAnnotationPresent(GET.class) || m.isAnnotationPresent(POST.class)\n        || m.isAnnotationPresent(PUT.class) || m.isAnnotationPresent(DELETE.class);\n}","tryCatchPattern":null,"preventionTips":["Only annotate HTTP resource methods/classes with @AuthorizationPolicy","In Kotlin, annotate the endpoint function following the documented suspend pattern","Secure non-endpoint methods with @RolesAllowed or programmatic checks instead"],"tags":["quarkus","build-time","security","jaxrs"],"backgroundTag":"annotation-on-non-endpoint","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"}