quarkusio/quarkus · error · java.lang.IllegalArgumentException

@PermissionAllowed instance that accepts method arguments mu

Error message

@PermissionAllowed instance that accepts method arguments must be placed on a method

What it means

A @PermissionsAllowed instance that consumes secured method arguments (computed permission, i.e. isComputed with param converters) must be placed on a method — the code needs MethodInfo of the secured method to capture argument values. If such a permission is placed on a class (or other non-method target), PermissionCacheKey construction throws this IllegalArgumentException at build time.

Source

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

            }

            private static boolean isNotDefaultStringPermission(Type classType) {
                return !STRING_PERMISSION.equals(classType.name());
            }
        }

        private static final class PermissionCacheKey {
            private final int[] methodParamIndexes;
            private final PermissionKey permissionKey;
            private final boolean computed;
            private final boolean passActionsToConstructor;
            private final String[] methodParamConverters;

            private PermissionCacheKey(PermissionKey permissionKey, AnnotationTarget securedTarget, MethodInfo constructor,
                    PermissionConverterGenerator paramConverterGenerator) {
                if (isComputed(permissionKey, constructor)) {
                    if (securedTarget.kind() != AnnotationTarget.Kind.METHOD) {
                        throw new IllegalArgumentException(
                                "@PermissionAllowed instance that accepts method arguments must be placed on a method");
                    }
                    MethodInfo securedMethod = securedTarget.asMethod();

                    // computed permission
                    this.permissionKey = permissionKey;
                    this.computed = true;
                    final boolean isSecondParamStringArr = !secondParamIsNotStringArr(constructor);

                    // determine if we want to pass actions param to Permission constructor
                    if (isSecondParamStringArr && !permissionKey.isQuarkusPermission()) {
                        int foundIx = findSecuredMethodParamIndex(securedMethod, constructor, 1,
                                permissionKey.paramsRemainder, permissionKey.params, -1, paramConverterGenerator.index)
                                .methodParamIdx();
                        // if (foundIx == -1) is false then user assigned second constructor param to a method param
                        this.passActionsToConstructor = foundIx == -1;
                    } else {
                        this.passActionsToConstructor = false;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Move the @PermissionsAllowed annotation with params from the class to the specific method whose arguments it needs.
  2. If class-wide security is needed, put a param-less @PermissionsAllowed (e.g. a plain permission name backed by @PermissionChecker) at class level and keep parameterized annotations on methods.

Example fix

// before
@PermissionsAllowed(value = "get", params = { "id" })
public class DocumentService { ... }

// after
public class DocumentService {
    @PermissionsAllowed(value = "get", params = { "id" })
    public Document get(Long id) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

// Rule: @PermissionsAllowed with params must live on a method, not a class.
// In an ArchUnit-style test:
// methods annotated @PermissionsAllowed with params attribute must have annotationTarget() == METHOD.

Prevention

When it happens

Trigger: Placing @PermissionsAllowed with a 'params' attribute referencing method arguments (computed permission) at class level, where securedTarget.kind() != METHOD.

Common situations: Hoisting a method-level annotation to the class to 'share' it; IDE quick-fix moving annotations; misunderstanding that class-level annotations apply to all methods and can use their params.

Related errors


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