{"record":{"id":"fb7a5f2c6acaa9c3","repo":"quarkusio/quarkus","slug":"interface-declaringclass-default-method-me","errorCode":null,"errorMessage":"Interface '${declaringClass}' default method '${method}' has security annotation.\nSecuring interface default methods is currently not supported, please secure\nthe interface implementation method instead.\n","messagePattern":"Interface '(.+?)' default method '(.+?)' has security annotation\\.\nSecuring interface default methods is currently not supported, please secure\nthe interface implementation method instead\\.\n","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/security/spi/src/main/java/io/quarkus/security/spi/SecurityTransformerBuildItem.java","lineNumber":536,"sourceCode":"            // add security annotation instances from interfaces direct implementors\n            var result = new HashSet<>(indexedAnnotationInstances);\n            for (var annotationInstance : indexedAnnotationInstances) {\n                final ClassInfo declaringClass;\n                if (annotationInstance.target().kind() == METHOD) {\n                    declaringClass = annotationInstance.target().asMethod().declaringClass();\n                } else if (annotationInstance.target().kind() == CLASS) {\n                    declaringClass = annotationInstance.target().asClass();\n                } else {\n                    // illegal state - this shouldn't happen\n                    continue;\n                }\n                if (shouldCheckForSecurityAnnotations(declaringClass, checkedInterfaces)) {\n                    // test that secured interface doesn't have default methods with security annotations\n                    // as CDI interceptors are not applied on them\n                    for (var securedInterfaceMethod : declaringClass.methods()) {\n                        if (securedInterfaceMethod.isDefault()\n                                && hasSecurityAnnotationDetectedByIndex(securedInterfaceMethod, annotationOverlay.index())) {\n                            throw new RuntimeException(\"\"\"\n                                    Interface '%s' default method '%s' has security annotation.\n                                    Securing interface default methods is currently not supported, please secure\n                                    the interface implementation method instead.\n                                    \"\"\".formatted(declaringClass.name().toString(), securedInterfaceMethod.name()));\n                        }\n                    }\n\n                    var implementorSecurityAnnotation = getImplementorsSecurityAnnotations(securityAnnotationName,\n                            declaringClass, repeatable);\n                    if (implementorSecurityAnnotation != null) {\n                        result.addAll(implementorSecurityAnnotation);\n                    }\n                }\n            }\n            return Collections.unmodifiableCollection(result);\n        }\n    }\n","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security/spi/src/main/java/io/quarkus/security/spi/SecurityTransformerBuildItem.java#L518-L554","documentation":"CDI interceptors (which enforce @RolesAllowed etc.) are not applied to interface default methods. Quarkus therefore fails the build when it detects a security annotation on a default method of a secured interface, telling the developer to secure the implementing method instead.","triggerScenarios":"Declaring an interface whose default method is annotated with @RolesAllowed/@Authenticated/@PermitAll while the interface is checked for security annotations (e.g. implemented by a CDI bean or REST resource).","commonSituations":"Adding default convenience methods with security annotations to a shared API interface; refactoring duplicated annotated code into interface default methods; copy-pasting annotated endpoint signatures into interfaces.","solutions":["Move the security annotation to the overriding implementation method in the concrete class.","Convert the default method to an abstract interface method and implement it in each implementing class with the annotation.","Extract shared logic into a helper bean and keep the security annotation on the concrete endpoint method."],"exampleFix":"// before\ninterface Greeting {\n    @RolesAllowed(\"admin\")\n    default String hello() { return \"hi\"; }\n}\n\n// after\nclass GreetingImpl implements Greeting {\n    @RolesAllowed(\"admin\")\n    public String hello() { return \"hi\"; }\n}","handlingStrategy":"validation","validationCode":"boolean ok(java.lang.Class<?> iface) {\n    for (java.lang.reflect.Method m : iface.getMethods()) {\n        if (m.isDefault() && m.getAnnotations().length > 0\n                && hasSecurityAnnotation(m)) return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never annotate interface default methods with @RolesAllowed/@Authenticated","Keep security annotations on classes/method implementations only","Review refactors that move annotated code into interfaces"],"tags":["security","cdi","interceptors","build-time"],"backgroundTag":"security-annotation-on-interface-default-method","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}