quarkusio/quarkus · error · java.lang.IllegalStateException

Method %s of class %s is annotated with multiple security an

Error message

Method %s of class %s is annotated with multiple security annotations

What it means

A method is annotated with @PermissionsAllowed together with another security annotation such as @DenyAll, @PermitAll, or @RolesAllowed. Quarkus does not allow combining @PermissionsAllowed with other security annotations on the same method because the authorization semantics would be ambiguous, so the build fails with an IllegalStateException.

Source

Thrown at extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java:447

        PermissionSecurityChecksBuilder gatherPermissionsAllowedAnnotations(
                Map<MethodInfo, AnnotationInstance> alreadyCheckedMethods,
                Map<ClassInfo, AnnotationInstance> alreadyCheckedClasses,
                List<AnnotationInstance> additionalClassInstances,
                Predicate<MethodInfo> hasAdditionalSecurityAnnotations) {

            List<PermissionKey> cache = new ArrayList<>();
            Map<MethodInfo, List<List<PermissionKey>>> classMethodToPermissionKeys = new HashMap<>();
            for (AnnotationInstance instance : permissionInstances) {

                AnnotationTarget target = instance.target();
                if (target.kind() == AnnotationTarget.Kind.METHOD) {
                    // method annotation
                    final MethodInfo methodInfo = target.asMethod();

                    // we don't allow combining @PermissionsAllowed with other security annotations as @DenyAll, ...
                    if (alreadyCheckedMethods.containsKey(methodInfo) || hasAdditionalSecurityAnnotations.test(methodInfo)) {
                        throw new IllegalStateException(
                                String.format("Method %s of class %s is annotated with multiple security annotations",
                                        methodInfo.name(), methodInfo.declaringClass()));
                    }

                    gatherPermissionKeys(instance, methodInfo, cache, targetToPermissionKeys);
                } else {
                    // class annotation

                    // add permissions for the class annotation if respective method haven't already been annotated
                    if (target.kind() == AnnotationTarget.Kind.CLASS) {
                        final ClassInfo clazz = target.asClass();

                        // ignore PermissionsAllowedInterceptor in security module
                        // we also need to check string as long as duplicate "PermissionsAllowedInterceptor" exists
                        // in RESTEasy Reactive, however this workaround should be removed when the interceptor is dropped
                        if (isPermissionsAllowedInterceptor(clazz)) {
                            continue;
                        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the conflicting security annotation (@RolesAllowed, @DenyAll, @PermitAll, etc.) from the method, keeping only @PermissionsAllowed
  2. Express the combined policy inside a single @PermissionsAllowed expression or permission checker
  3. Move the broad policy to class level and keep method-level only @PermissionsAllowed

Example fix

// before
@RolesAllowed("admin")
@PermissionsAllowed("book:delete")
public void delete(Long id) {...}

// after
@PermissionsAllowed("book:delete")
public void delete(Long id) {...}
Defensive patterns

Strategy: validation

Validate before calling

for (Annotation a : MyResource.class.getMethod("delete", Long.class).getAnnotations()) {
    if (!(a instanceof PermissionsAllowed) && SECURITY_ANNOTATIONS.contains(a.annotationType()))
        throw new IllegalStateException("@PermissionsAllowed must not be combined with " + a.annotationType());
}

Prevention

When it happens

Trigger: Annotating one method with both @PermissionsAllowed and @DenyAll/@PermitAll/@RolesAllowed/@Authenticated; detected in gatherPermissionsAllowedAnnotations via alreadyCheckedMethods or hasAdditionalSecurityAnnotations.

Common situations: Applying class-level security defaults then adding method-level @PermissionsAllowed on top of a leftover @RolesAllowed; stacking annotations while experimenting with the security API.

Related errors


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