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
- Remove the conflicting security annotation (@RolesAllowed, @DenyAll, @PermitAll, etc.) from the method, keeping only @PermissionsAllowed
- Express the combined policy inside a single @PermissionsAllowed expression or permission checker
- 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
- One security annotation per method — prefer @PermissionsAllowed exclusively
- Search the class for leftover @RolesAllowed/@DenyAll before adding @PermissionsAllowed
- Codify the rule with an ArchUnit test
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
- Class %s is annotated with multiple security annotations %s
- @PermissionChecker annotation placed on the '%s' attribute '
- @PermissionChecker annotation instance placed on the '%s' re
- Detected two @PermissionChecker annotations with same value
- @PermissionChecker method '%s' declares checked exceptions w
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f3f24bb09b697229.
Report an issue: GitHub.