{"record":{"id":"a26c10c29a9a148d","repo":"quarkusio/quarkus","slug":"permissionchecker-s-matches-permission-s-an","errorCode":null,"errorMessage":"@PermissionChecker '%s' matches permission '%s' and actions '%s' on secured method '%s', but\n                                the @PermissionsAllowed instance specified custom permission '%s'. Both cannot be supported.\n                                Please choose one.\n                                ","messagePattern":"@PermissionChecker '(.+?)' matches permission '(.+?)' and actions '(.+?)' on secured method '(.+?)', but\n                                the @PermissionsAllowed instance specified custom permission '(.+?)'\\. Both cannot be supported\\.\n                                Please choose one\\.\n                                ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java","lineNumber":1210,"sourceCode":"        }\n\n        private static final class PermissionKey {\n\n            private final String name;\n            private final Set<String> actions;\n            private final String[] params;\n            private final String[] paramsRemainder;\n            private final Type clazz;\n            private final boolean inclusive;\n            private final PermissionCheckerMetadata permissionChecker;\n\n            private PermissionKey(String name, Set<String> actions, String[] params, Type clazz, boolean inclusive,\n                    PermissionCheckerMetadata permissionChecker, AnnotationTarget permsAllowedTarget) {\n                this.permissionChecker = permissionChecker;\n                this.name = name;\n                if (permissionChecker != null) {\n                    if (isNotDefaultStringPermission(clazz)) {\n                        throw new IllegalArgumentException(\"\"\"\n                                @PermissionChecker '%s' matches permission '%s' and actions '%s' on secured method '%s', but\n                                the @PermissionsAllowed instance specified custom permission '%s'. Both cannot be supported.\n                                Please choose one.\n                                \"\"\".formatted(PermissionSecurityChecksBuilder.toString(permissionChecker.checkerMethod()), name,\n                                actions, PermissionSecurityChecksBuilder.toString(permsAllowedTarget), clazz.name()));\n                    }\n                    this.clazz = Type.create(DotName.createSimple(permissionChecker.generatedClassName()), Type.Kind.CLASS);\n                } else {\n                    this.clazz = clazz;\n                }\n                this.inclusive = inclusive;\n                if (!actions.isEmpty()) {\n                    this.actions = actions;\n                } else {\n                    this.actions = null;\n                }\n\n                if (params == null || params.length == 0) {","sourceCodeStart":1192,"sourceCodeEnd":1228,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java#L1192-L1228","documentation":"A @PermissionsAllowed entry can be satisfied either by a @PermissionChecker method or by a custom Permission implementation — not both. When a permission name (and actions) matches an existing @PermissionChecker but the annotation also specifies a non-default custom permission class, Quarkus throws this IllegalArgumentException in the PermissionKey constructor, naming the checker, the secured target, and the custom class.","triggerScenarios":"@PermissionsAllowed(value=\"p\", clazz=MyPermission.class) where a @PermissionChecker(\"p\") method exists (with matching actions), so the name-based checker lookup collides with the explicit custom class.","commonSituations":"Adding a @PermissionChecker for a permission already secured with a custom Permission class; renaming a custom permission so it now collides with an existing checker name; team members independently wiring both mechanisms for the same permission.","solutions":["Choose one mechanism: remove the clazz attribute to use the @PermissionChecker, or remove/rename the @PermissionChecker method to keep the custom Permission class.","Rename the custom permission so it no longer matches the checker's permission name if both permissions must coexist.","Keep actions consistent — the collision is triggered by matched name+actions; adjusting actions alone does not fix it, resolve the overlap explicitly."],"exampleFix":"// before (both defined)\n@PermissionChecker(\"get\")\nPermissionChecker getChecker() { ... }\n@PermissionsAllowed(value = \"get\", clazz = GetPermission.class)\n\n// after (keep custom permission, drop checker)\n@PermissionsAllowed(value = \"get\", clazz = GetPermission.class)","handlingStrategy":"validation","validationCode":"// Before adding a @PermissionChecker, check no @PermissionsAllowed with clazz= uses the same name:\n// grep -rn \"clazz\\s*=\" src/main/java | while read l; do\n//   name=$(extract value); grep -rn \"@PermissionChecker(\\\"$name\\\")\" src/main/java && echo \"conflict: $l\"\n// done","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide per permission name: either a @PermissionChecker bean or a custom Permission class, never both.","Keep a registry of permission names and their mechanism.","When introducing a checker, search the codebase for custom permission classes with the same name."],"tags":["quarkus","security","permissionchecker","custom-permission"],"backgroundTag":"permission-checker-conflict","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"}