{"record":{"id":"48a02f598b346480","repo":"quarkusio/quarkus","slug":"permissionchecker-annotation-placed-on-the-s-a","errorCode":null,"errorMessage":"@PermissionChecker annotation placed on the '%s' attribute 'value' must not be blank","messagePattern":"@PermissionChecker annotation placed on the '(.+?)' attribute 'value' must not be blank","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java","lineNumber":150,"sourceCode":"                    // so the checker method must be either public or package-private\n                    throw new RuntimeException(\"Private method '\" + toString(checkerMethod)\n                            + \"' cannot be annotated with the @PermissionChecker annotation\");\n                }\n                if (Modifier.isStatic(checkerMethod.flags())) {\n                    // checkers must be CDI bean member methods for now, so the checker method must not be static\n                    throw new RuntimeException(\"Static method '\" + toString(checkerMethod)\n                            + \"' cannot be annotated with the @PermissionChecker annotation\");\n                }\n                boolean isReactive = isUniBoolean(checkerMethod);\n                if (!isReactive && !isPrimitiveBoolean(checkerMethod)) {\n                    throw new RuntimeException((\"@PermissionChecker method '%s' has return type '%s', but only \" +\n                            \"supported return types are 'boolean' and 'Uni<Boolean>'. \")\n                            .formatted(toString(checkerMethod), checkerMethod.returnType().name()));\n                }\n\n                var permissionName = annotationInstance.value().asString();\n                if (permissionName.isBlank()) {\n                    throw new IllegalArgumentException(\n                            \"@PermissionChecker annotation placed on the '%s' attribute 'value' must not be blank\"\n                                    .formatted(toString(checkerMethod)));\n                }\n                boolean isBlocking = checkerMethod.hasDeclaredAnnotation(BLOCKING);\n                if (isBlocking && isReactive) {\n                    throw new IllegalArgumentException(\"\"\"\n                            @PermissionChecker annotation instance placed on the '%s' returns 'Uni<Boolean>' and is\n                            annotated with the @Blocking annotation; if you need to block, please return 'boolean'\n                            \"\"\".formatted(toString(checkerMethod)));\n                }\n\n                var generatedPermissionClassName = getGeneratedPermissionName(checkerMethod, permissionCheckerIndex++);\n                var methodParamMappers = new MethodParameterMapper[checkerMethod.parametersCount()];\n                var generatedPermissionConstructor = getGeneratedPermissionConstructor(checkerMethod, methodParamMappers);\n                var checkerMetadata = new PermissionCheckerMetadata(checkerMethod, generatedPermissionClassName,\n                        isReactive, generatedPermissionConstructor, methodParamMappers, isBlocking);\n\n                if (permissionCheckers.containsKey(permissionName)) {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java#L132-L168","documentation":"Quarkus's security deployment step scans methods annotated with @PermissionChecker. Each such method must carry a non-blank permission name in the annotation's 'value' attribute, since this name is used both as the map key linking checkers to @PermissionsAllowed requirements and as the generated Permission class name. An empty or whitespace-only value is rejected at build time with this IllegalArgumentException.","triggerScenarios":"Annotating a method with @PermissionChecker(value=\"\") or @PermissionChecker(value=\"   \") (blank string) on a CDI bean method during application build.","commonSituations":"Copy-pasting @PermissionChecker from examples and forgetting to fill in the value; building the name dynamically and accidentally leaving an empty constant; refactoring that empties the string.","solutions":["Set a non-blank value on the @PermissionChecker annotation, e.g. @PermissionChecker(value=\"can-read\")","Ensure the constant/enum feeding the value is initialized to a real name, not an empty string","If you intended no permission name, remove the @PermissionChecker annotation entirely"],"exampleFix":"// before\n@PermissionChecker(\"\")\nboolean canRead(Book book) { return true; }\n\n// after\n@PermissionChecker(\"book:read\")\nboolean canRead(Book book) { return true; }","handlingStrategy":"validation","validationCode":"// check before build\nPermissionChecker pc = MyBean.class.getMethod(\"canRead\", Book.class).getAnnotation(PermissionChecker.class);\nif (pc == null || pc.value().isBlank()) throw new IllegalStateException(\"@PermissionChecker value must not be blank\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a named constant or enum constant as the permission value","Add an ArchUnit/unit test asserting all @PermissionChecker values are non-blank","Code-review new security annotations for filled-in values"],"tags":["quarkus","security","build-time","annotation"],"backgroundTag":"invalid-annotation-value","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"}