quarkusio/quarkus · error · java.lang.RuntimeException
Permission constructor '%s' first argument must be '%s'
Error message
Permission constructor '%s' first argument must be '%s'
What it means
The single constructor of a custom Permission class must accept the permission name as its first parameter of type java.lang.String, since Quarkus instantiates it with the @PermissionsAllowed value as the first argument. A constructor with no parameters or a non-String first parameter is rejected at build time.
Source
Thrown at extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java:401
// to validate it
classSignatureToConstructor.put(key.classSignature(),
key.permissionChecker.quarkusPermissionConstructor());
permissionCheckers.remove(key.permissionChecker);
continue;
}
// validate permission class
final ClassInfo clazz = index.getClassByName(key.clazz.name());
Objects.requireNonNull(clazz);
if (clazz.constructors().size() != 1) {
throw new RuntimeException(
String.format("Permission class '%s' has %d constructors, exactly one is allowed",
key.classSignature(), clazz.constructors().size()));
}
var constructor = clazz.constructors().get(0);
// first constructor parameter must be permission name
if (constructor.parametersCount() == 0 || !STRING.equals(constructor.parameterType(0).name())) {
throw new RuntimeException(
String.format("Permission constructor '%s' first argument must be '%s'",
clazz.name().toString(), String.class.getName()));
}
// rest of validation needs to be done for computed classes only and per each secured method
// therefore we do it later
// cache validation result
classSignatureToConstructor.put(key.classSignature(), constructor);
}
}
}
}
if (!permissionCheckers.isEmpty()) {
if (permissionCheckers.size() > 1) {
throw new RuntimeException("""
Found @PermissionChecker annotation instances that authorize the '%s' permissions, however
no @PermissionsAllowed annotation instance requires these permissions
""".formatted(String.join(",", permissionCheckers.values())));View on GitHub (pinned to e1c734241f)
Solutions
- Add a String permission-name parameter as the first constructor argument
- Reorder constructor parameters so String comes first
- If no name is meaningful, still accept it and ignore/store it in the constructor
Example fix
// before
public class MyPerm implements Permission {
public MyPerm(Book b) {...}
}
// after
public class MyPerm implements Permission {
public MyPerm(String name, Book b) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
Constructor<?> c = MyPerm.class.getConstructors()[0];
if (c.getParameterCount() == 0 || !c.getParameterTypes()[0].equals(String.class))
throw new IllegalStateException("Permission constructor first parameter must be java.lang.String"); Prevention
- Always model permissions as (String name, <secured params>...)
- Copy the official Quarkus custom-permission example as a template
- Add a reflection test asserting the constructor signature
When it happens
Trigger: Defining a permission class whose sole constructor is MyPerm(Book b) or MyPerm() and referencing it from @PermissionsAllowed; validated when validatePermissionClasses inspects constructor.parameterType(0).
Common situations: Modeling permissions around the checked resource only and omitting the name parameter; following an outdated tutorial predating the name-parameter requirement.
Related errors
- Permission class '%s' has %d constructors, exactly one is al
- @CachedResults class must be an interface or declare a no-ar
- @PermissionChecker annotation placed on the '%s' attribute '
- @PermissionChecker annotation instance placed on the '%s' re
- Detected two @PermissionChecker annotations with same value
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ebb7991a31848567.
Report an issue: GitHub.