{"record":{"id":"88ec65c15a99fb3c","repo":"quarkusio/quarkus","slug":"method-s-s-parameter-s-cannot-be-converted","errorCode":null,"errorMessage":"Method '%s#%s' parameter '%s' cannot be converted to a Permission constructor parameter\n                            as required by the '@PermissionsAllowed#params' attribute. Parameter expression references '%s'\n                            that has type '%s' which is not a class. Only class methods or fields can be mapped\n                            to a Permission constructor parameter.","messagePattern":"Method '(.+?)#(.+?)' parameter '(.+?)' cannot be converted to a Permission constructor parameter\n                            as required by the '@PermissionsAllowed#params' attribute\\. Parameter expression references '(.+?)'\n                            that has type '(.+?)' which is not a class\\. Only class methods or fields can be mapped\n                            to a Permission constructor parameter\\.","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java","lineNumber":1692,"sourceCode":"            validateNestedParams(nestedParams, 0, paramType, securedMethod, methodParamIdx);\n\n            converterTasks.add(new ConverterTask(converterName, nestedParams, paramType));\n\n            var methodHandleRuntimeVal = recorder.createPermissionMethodConverter(converterName, getClazz());\n            converterNameToMethodHandle.put(converterName, methodHandleRuntimeVal);\n            return converterName;\n        }\n\n        private void validateNestedParams(String[] nestedParams, int nestedParamIdx, Type outerType,\n                MethodInfo securedMethod, int methodParamIdx) {\n            if (nestedParamIdx == nestedParams.length) {\n                return;\n            }\n\n            var paramExpression = nestedParams[nestedParamIdx];\n            var outerClass = index.getClassByName(outerType.name());\n            if (outerClass == null) {\n                throw new IllegalArgumentException(\"\"\"\n                            Method '%s#%s' parameter '%s' cannot be converted to a Permission constructor parameter\n                            as required by the '@PermissionsAllowed#params' attribute. Parameter expression references '%s'\n                            that has type '%s' which is not a class. Only class methods or fields can be mapped\n                            to a Permission constructor parameter.\n                        \"\"\".formatted(securedMethod.declaringClass().name(), securedMethod.name(),\n                        securedMethod.parameterName(methodParamIdx), paramExpression, outerType.name()));\n            }\n\n            var method = outerClass.method(paramExpression);\n            if (method == null) {\n                method = outerClass.method(toFieldGetter(paramExpression));\n            }\n            if (method != null) {\n                if (!Modifier.isPublic(method.flags())) {\n                    throw new IllegalArgumentException(\"\"\"\n                            Method '%s#%s' parameter '%s' cannot be mapped to a Permission constructor parameter,\n                            because expression '%s' specified in the '@PermissionsAllowed#params' attribute is\n                            accessible from method '%s#%s' which is not a public method.","sourceCodeStart":1674,"sourceCodeEnd":1710,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java#L1674-L1710","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Change the expression so the last traversed member resolves to a class type (e.g. box the primitive or navigate a wrapper object).","Make sure the referenced type is part of the application/indexed classes; if it lives in a dependency, ensure it is Jandex-indexed.","Replace the nested-expression navigation with a custom Permission class or a PermissionChecker method that computes the value in plain code.","If the member is a method or field on an interface, point the expression at the concrete class instead."],"exampleFix":"// before\n@PermissionsAllowed(value = \"read\", params = \"order.qty\")\npublic void read(Order order) { ... } // qty is int (not a class)\n\n// after\n@PermissionsAllowed(value = \"read\", params = \"order.customer\")\npublic void read(Order order) { ... } // navigate a class-typed member","handlingStrategy":"validation","validationCode":"// before annotating, ensure every nested expression member resolves to a class type\n// e.g. 'order.customer' - customer must be a class-typed field/getter, not int/arrays","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only navigate into class-typed members in params expressions","Keep all traversed types Jandex-indexed (part of the app or indexed jars)","Prefer custom Permission classes for non-trivial value derivation"],"tags":["quarkus","security","permissionsallowed","build-time"],"backgroundTag":"permissions-allowed-expression-mapping","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}