quarkusio/quarkus · error · java.lang.IllegalArgumentException
@PermissionChecker annotation placed on the '%s' attribute '
Error message
@PermissionChecker annotation placed on the '%s' attribute 'value' must not be blank
What it means
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.
Source
Thrown at extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java:150
// so the checker method must be either public or package-private
throw new RuntimeException("Private method '" + toString(checkerMethod)
+ "' cannot be annotated with the @PermissionChecker annotation");
}
if (Modifier.isStatic(checkerMethod.flags())) {
// checkers must be CDI bean member methods for now, so the checker method must not be static
throw new RuntimeException("Static method '" + toString(checkerMethod)
+ "' cannot be annotated with the @PermissionChecker annotation");
}
boolean isReactive = isUniBoolean(checkerMethod);
if (!isReactive && !isPrimitiveBoolean(checkerMethod)) {
throw new RuntimeException(("@PermissionChecker method '%s' has return type '%s', but only " +
"supported return types are 'boolean' and 'Uni<Boolean>'. ")
.formatted(toString(checkerMethod), checkerMethod.returnType().name()));
}
var permissionName = annotationInstance.value().asString();
if (permissionName.isBlank()) {
throw new IllegalArgumentException(
"@PermissionChecker annotation placed on the '%s' attribute 'value' must not be blank"
.formatted(toString(checkerMethod)));
}
boolean isBlocking = checkerMethod.hasDeclaredAnnotation(BLOCKING);
if (isBlocking && isReactive) {
throw new IllegalArgumentException("""
@PermissionChecker annotation instance placed on the '%s' returns 'Uni<Boolean>' and is
annotated with the @Blocking annotation; if you need to block, please return 'boolean'
""".formatted(toString(checkerMethod)));
}
var generatedPermissionClassName = getGeneratedPermissionName(checkerMethod, permissionCheckerIndex++);
var methodParamMappers = new MethodParameterMapper[checkerMethod.parametersCount()];
var generatedPermissionConstructor = getGeneratedPermissionConstructor(checkerMethod, methodParamMappers);
var checkerMetadata = new PermissionCheckerMetadata(checkerMethod, generatedPermissionClassName,
isReactive, generatedPermissionConstructor, methodParamMappers, isBlocking);
if (permissionCheckers.containsKey(permissionName)) {View on GitHub (pinned to e1c734241f)
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
Example fix
// before
@PermissionChecker("")
boolean canRead(Book book) { return true; }
// after
@PermissionChecker("book:read")
boolean canRead(Book book) { return true; } Defensive patterns
Strategy: validation
Validate before calling
// check before build
PermissionChecker pc = MyBean.class.getMethod("canRead", Book.class).getAnnotation(PermissionChecker.class);
if (pc == null || pc.value().isBlank()) throw new IllegalStateException("@PermissionChecker value must not be blank"); Prevention
- 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
When it happens
Trigger: Annotating a method with @PermissionChecker(value="") or @PermissionChecker(value=" ") (blank string) on a CDI bean method during application build.
Common situations: 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.
Related errors
- The @AuthorizationPolicy annotation placed on '<target>' mus
- Only one of the '<annotations>' annotations can be applied o
- Security annotations '<annotations>' cannot be applied on th
- Only one of the '<annotations>' annotations can be applied o
- The configuration ${clazz} is missing the @ConfigRoot annota
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/48a02f598b346480.
Report an issue: GitHub.