quarkusio/quarkus · error · java.lang.IllegalArgumentException

Method ' # ' parameter ' ' cannot be converted to a…

Error message

Method '%s#%s' parameter '%s' cannot be converted to a Permission constructor parameter
                            as required by the '@PermissionsAllowed#params' attribute. Parameter expression references '%s'
                            that has type '%s' which is not a class. Only class methods or fields can be mapped
                            to a Permission constructor parameter.

What it means

Quarkus Security's @PermissionsAllowed lets method parameters be converted into Permission constructor arguments via expression strings like 'param.attr.attr'. This error is thrown at build time when an intermediate expression segment resolves to a type that is not a class (e.g. a primitive, array, or interface-only resolution from the Jandex index), so nested navigation cannot continue. Only method or field accesses on classes can be mapped to Permission constructor parameters.

Solutions

  1. Change the expression so the last traversed member resolves to a class type (e.g. box the primitive or navigate a wrapper object).
  2. Make sure the referenced type is part of the application/indexed classes; if it lives in a dependency, ensure it is Jandex-indexed.
  3. Replace the nested-expression navigation with a custom Permission class or a PermissionChecker method that computes the value in plain code.
  4. If the member is a method or field on an interface, point the expression at the concrete class instead.

Example fix

// before
@PermissionsAllowed(value = "read", params = "order.qty")
public void read(Order order) { ... } // qty is int (not a class)

// after
@PermissionsAllowed(value = "read", params = "order.customer")
public void read(Order order) { ... } // navigate a class-typed member
Defensive patterns

Strategy: validation

Validate before calling

// before annotating, ensure every nested expression member resolves to a class type
// e.g. 'order.customer' - customer must be a class-typed field/getter, not int/arrays

Prevention

When it happens

Trigger: Annotating a method with @PermissionsAllowed(params="...") whose expression traverses into a member whose declared type is not resolvable as a class in the Jandex index (primitive types, arrays, or types not indexed).

Common situations: Navigating expressions into primitive getters (e.g. 'p.count' where count is int), into arrays, or into classes excluded from the index; using record components or Lombok-generated accessors whose resolved types confuse the expression walk.

Related errors


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

Appendix: source

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

            validateNestedParams(nestedParams, 0, paramType, securedMethod, methodParamIdx);

            converterTasks.add(new ConverterTask(converterName, nestedParams, paramType));

            var methodHandleRuntimeVal = recorder.createPermissionMethodConverter(converterName, getClazz());
            converterNameToMethodHandle.put(converterName, methodHandleRuntimeVal);
            return converterName;
        }

        private void validateNestedParams(String[] nestedParams, int nestedParamIdx, Type outerType,
                MethodInfo securedMethod, int methodParamIdx) {
            if (nestedParamIdx == nestedParams.length) {
                return;
            }

            var paramExpression = nestedParams[nestedParamIdx];
            var outerClass = index.getClassByName(outerType.name());
            if (outerClass == null) {
                throw new IllegalArgumentException("""
                            Method '%s#%s' parameter '%s' cannot be converted to a Permission constructor parameter
                            as required by the '@PermissionsAllowed#params' attribute. Parameter expression references '%s'
                            that has type '%s' which is not a class. Only class methods or fields can be mapped
                            to a Permission constructor parameter.
                        """.formatted(securedMethod.declaringClass().name(), securedMethod.name(),
                        securedMethod.parameterName(methodParamIdx), paramExpression, outerType.name()));
            }

            var method = outerClass.method(paramExpression);
            if (method == null) {
                method = outerClass.method(toFieldGetter(paramExpression));
            }
            if (method != null) {
                if (!Modifier.isPublic(method.flags())) {
                    throw new IllegalArgumentException("""
                            Method '%s#%s' parameter '%s' cannot be mapped to a Permission constructor parameter,
                            because expression '%s' specified in the '@PermissionsAllowed#params' attribute is
                            accessible from method '%s#%s' which is not a public method.

View on GitHub (pinned to e1c734241f)