quarkusio/quarkus · error · java.lang.RuntimeException

Class '%s' is annotated with '%s' and '%s' security annotati

Error message

Class '%s' is annotated with '%s' and '%s' security annotations,
                                    however security annotations cannot be combined.

What it means

A class annotated with a custom/additional security annotation (registered via AdditionalSecurityAnnotationBuildItem) cannot also carry a standard Quarkus security annotation such as @RolesAllowed/@Authenticated on the same target — security annotations cannot be combined. The build fails naming both annotations.

Source

Thrown at extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java:1111

        permitAllGatherer.gatherClassSecurityAnnotations();
        authenticatedGatherer.gatherClassSecurityAnnotations();
        denyAllGatherer.gatherClassSecurityAnnotations();
        rolesAllowedGatherer.gatherClassSecurityAnnotations();

        // we already validated that annotation target doesn't have more than one security check annotation
        // now validate that the same annotation target doesn't have both security check and authorization policy annotation
        securityTransformer.getSecurityAnnotationNames(AUTHORIZATION_POLICY)
                .forEach(additionalSecAnnName -> index
                        .getAnnotations(additionalSecAnnName)
                        .stream()
                        .filter(ai -> ai.target().kind() == AnnotationTarget.Kind.CLASS)
                        .map(ai -> ai.target().asClass())
                        .filter(ai -> securityTransformer.hasSecurityAnnotation(ai, SECURITY_CHECK))
                        .findFirst()
                        .ifPresent(ci -> {
                            var securityAnnotation = securityTransformer.findFirstSecurityAnnotation(ci, SECURITY_CHECK)
                                    .get().name();
                            throw new RuntimeException("""
                                    Class '%s' is annotated with '%s' and '%s' security annotations,
                                    however security annotations cannot be combined.
                                    """.formatted(ci.name(), additionalSecAnnName, securityAnnotation));
                        }));

        /*
         * Handle additional secured methods by adding the denyAll/rolesAllowed check to all public non-static methods
         * that don't have same security annotations
         */
        for (AdditionalSecured additionalSecuredMethod : additionalSecuredMethods) {
            if (!isPublicNonStaticNonConstructor(additionalSecuredMethod.methodInfo)) {
                continue;
            }
            if (hasAdditionalSecurityAnnotations.test(additionalSecuredMethod.methodInfo)) {
                continue;
            }
            AnnotationInstance alreadyExistingInstance = methodToInstanceCollector.get(additionalSecuredMethod.methodInfo);
            if (additionalSecuredMethod.rolesAllowed.isPresent()) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove one of the two annotations from the class — either the custom annotation or the standard security annotation.
  2. If the custom annotation should imply the standard check, model that in the annotation's own build step instead of combining annotations.
  3. Move the standard annotation to specific methods rather than combining them at class level, if the framework supports method-level separation.

Example fix

// before
@RolesAllowed("admin")
@CustomSecurity
public class AdminResource { ... }

// after
@CustomSecurity
public class AdminResource { ... } // handle roles inside the custom check
Defensive patterns

Strategy: validation

Validate before calling

// fail fast if both a custom and a standard security annotation are present on a class
if (AdminResource.class.isAnnotationPresent(RolesAllowed.class) && AdminResource.class.isAnnotationPresent(CustomSecurity.class)) throw new IllegalStateException("security annotations cannot be combined");

Prevention

When it happens

Trigger: A class carries both a registered custom security annotation and a standard security annotation (e.g. @MyCustomAuth + @RolesAllowed) at the class level.

Common situations: Introducing a custom security annotation while legacy @RolesAllowed remains on the same class; library classes annotated with standard annotations being re-annotated with a company-specific annotation during a migration.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/cbffe69272394a6f. Report an issue: GitHub.