quarkusio/quarkus · error · java.lang.IllegalArgumentException

Method '%s#%s' parameter '%s' cannot be mapped to a Permissi

Error message

Method '%s#%s' parameter '%s' cannot be mapped to a Permission constructor parameter,
                            because expression '%s' specified in the '@PermissionsAllowed#params' attribute is only
                            accessible from field '%s#%s' which is not a public field. Please declare a getter method.

What it means

When an @PermissionsAllowed params expression segment resolves to a field (no matching method/getter exists), Quarkus requires that field be public because it will be read reflectively to build the Permission argument. Non-public fields trigger this build-time error with a suggestion to declare a getter method.

Source

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

                            because expression '%s' specified in the '@PermissionsAllowed#params' attribute is
                            accessible from method '%s#%s' which is not a public method.
                            """.formatted(securedMethod.declaringClass().name(), securedMethod.name(),
                            securedMethod.parameterName(methodParamIdx), paramExpression, method.declaringClass().name(),
                            method.name()));
                }
                validateNestedParams(nestedParams, nestedParamIdx + 1, method.returnType(), securedMethod, methodParamIdx);
            } else {
                var field = outerClass.field(paramExpression);
                if (field == null) {
                    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 does not
                            match any method or field of the class '%s'.
                            """.formatted(securedMethod.declaringClass().name(), securedMethod.name(),
                            securedMethod.parameterName(methodParamIdx), paramExpression, outerClass.name()));
                }
                if (!Modifier.isPublic(field.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 only
                            accessible from field '%s#%s' which is not a public field. Please declare a getter method.
                            """.formatted(securedMethod.declaringClass().name(), securedMethod.name(),
                            securedMethod.parameterName(methodParamIdx), paramExpression, field.declaringClass().name(),
                            field.name()));
                }
                validateNestedParams(nestedParams, nestedParamIdx + 1, field.type(), securedMethod, methodParamIdx);
            }
        }

        private Expr generateNestedParam(String[] nestedParams, int nestedParamIdx, Expr outer,
                BlockCreator bc, Type outerType) {
            if (nestedParamIdx == nestedParams.length) {
                return outer;
            }

            // param name or getter name

View on GitHub (pinned to e1c734241f)

Solutions

  1. Declare a public getter for the field and reference the getter-style name in the params expression.
  2. Make the field public (less desirable, but allowed).
  3. Rename the params expression to match the existing public accessor name.
  4. Compute the value in a custom Permission or @PermissionChecker rather than navigating the field.

Example fix

// before
class Order { private String owner; }
@PermissionsAllowed(value="read", params="order.owner")

// after
class Order { private String owner; public String getOwner() { return owner; } }
@PermissionsAllowed(value="read", params="order.owner") // resolved via public getter
Defensive patterns

Strategy: validation

Validate before calling

// ensure a public field or public getter exists for each params segment
boolean ok = java.lang.reflect.Modifier.isPublic(Order.class.getField("owner").getModifiers());

Prevention

When it happens

Trigger: An expression segment matches a private/package-private/protected field of the traversed class and no public getter method with the same name (or getX/isX form) exists.

Common situations: Entities with private fields and non-standard getter names; expressions written against field names when only differently-named getters exist; records/components whose accessors don't follow the resolved naming convention.

Related errors


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