quarkusio/quarkus · error · IllegalStateException
QuarkusPermission should never be assigned to a SecurityIden
Error message
QuarkusPermission should never be assigned to a SecurityIdentity. This permission can only be set to the @PermissionsAllowed#permission attribute by Quarkus itself.
What it means
QuarkusPermission is an internal Permission marker placed inside @PermissionsAllowed checks to represent arbitrary action strings. Its implies() is intentionally unimplemented: it should never be the possessed permission of a SecurityIdentity, so any attempt to use it for an authorization decision throws IllegalStateException.
Source
Thrown at extensions/security/runtime/src/main/java/io/quarkus/security/runtime/QuarkusPermission.java:104
try {
if (isReactive()) {
return isGrantedUni(identity);
} else {
return Uni.createFrom().item(isGranted(identity));
}
} catch (Throwable throwable) {
return Uni.createFrom().failure(throwable);
}
}
/**
* @throws IllegalStateException for this permission can only be set to the {@link PermissionsAllowed#permission()}
*/
@Override
public final boolean implies(Permission requiredPermission) {
// possessed permission implies required permission
// this is required permission, not the possessed one
throw new IllegalStateException("QuarkusPermission should never be assigned to a SecurityIdentity. "
+ "This permission can only be set to the @PermissionsAllowed#permission attribute by Quarkus itself.");
}
@Override
public final String getActions() {
return "";
}
@Override
public final boolean equals(Object object) {
return this == object;
}
@Override
public final int hashCode() {
return Objects.hash(toString());
}
View on GitHub (pinned to e1c734241f)
Solutions
- Never add QuarkusPermission instances to a SecurityIdentity; use real Permission implementations (BasicPermission subclasses or custom ones) for possessed permissions.
- In augmentors/filters, filter out QuarkusPermission instances when copying permission collections.
- If you need @PermissionsAllowed semantics for identity checks, use PermissionVerifier/permission checkers instead of the internal permission class.
Example fix
// before
identity.addPermission(new QuarkusPermission("read"));
// after
identity.addPermission(new BasicPermission("app") {
{ setName("read"); }
}); Defensive patterns
Strategy: type-guard
Validate before calling
// filter internal permissions out before attaching to an identity
Permission[] safe = Stream.of(permissions)
.filter(p -> !(p instanceof QuarkusPermission))
.toArray(Permission[]::new); Type guard
boolean isAssignable(Permission possessed, Permission required) {
return !(possessed instanceof QuarkusPermission) && possessed.implies(required);
} Prevention
- Never add QuarkusPermission to a SecurityIdentity
- Use real Permission types for identity permissions
- Filter annotation-derived permissions in augmentors
When it happens
Trigger: Adding a QuarkusPermission to a SecurityIdentity (e.g. via identity.addPermission(new QuarkusPermission(...))) or a custom SecurityIdentityAugmentor that propagates it; then an authorization check calls implies() on it.
Common situations: Custom identity augmentors copying permissions blindly from PermissionsAllowed metadata; reflection-based code that recreates permissions from annotation values; debugging code that prints/adds all permissions of a check.
Related errors
- WebSocket endpoint '%s' superclass '%s' is secured with the
- WebSocket endpoint '%s' has method '%s' secured with the '%s
- Cannot transform exception ${exception}
- Unable to determine if bean '${className}' is available
- HTTP Security policy applied only on Quarkus REST cannot be
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/cc21a958cbf5f506.
Report an issue: GitHub.