quarkusio/quarkus · error · UnsupportedOperationException
retrieving all roles not supported when JAX-RS security cont
Error message
retrieving all roles not supported when JAX-RS security context has been replaced
What it means
This UnsupportedOperationException is thrown by the synthetic SecurityContext that Quarkus REST (RESTEasy Reactive) installs when application code replaced the JAX-RS SecurityContext via a filter (SecurityContextOverrideHandler). Because the overriding code fully controls identity/role checks, the framework cannot enumerate all roles, so getRoles() is intentionally unsupported. Only hasRole(String) delegation to the replaced context is provided.
Source
Thrown at extensions/resteasy-reactive/rest/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/security/SecurityContextOverrideHandler.java:76
@Override
public SecurityIdentity apply(SecurityIdentity old) {
Set<Credential> oldCredentials = old.getCredentials();
Set<Permission> oldPermissions = old.getPermissions();
Map<String, Object> oldAttributes = old.getAttributes();
SecurityIdentity newIdentity = new SecurityIdentity() {
@Override
public Principal getPrincipal() {
return modified.getUserPrincipal();
}
@Override
public boolean isAnonymous() {
return modified.getUserPrincipal() == null;
}
@Override
public Set<String> getRoles() {
throw new UnsupportedOperationException(
"retrieving all roles not supported when JAX-RS security context has been replaced");
}
@Override
public boolean hasRole(String role) {
return modified.isUserInRole(role);
}
@SuppressWarnings("unchecked")
@Override
public <T extends Credential> T getCredential(Class<T> credentialType) {
for (Credential cred : getCredentials()) {
if (credentialType.isAssignableFrom(cred.getClass())) {
return (T) cred;
}
}
return null;
}View on GitHub (pinned to e1c734241f)
Solutions
- Do not call getRoles() on the replaced SecurityContext; use hasRole("role") for individual checks instead of enumerating roles
- If you need role enumeration, have your custom SecurityContext implement getRoles() yourself before installing it via setSecurityContext()
- Keep Quarkus-managed SecurityIdentity intact: use IdentityProvider / SecurityIdentityAugmentor to add roles instead of replacing the SecurityContext
- If you only replaced the context for a different principal, consider augmenting the existing SecurityIdentity rather than overriding the whole SecurityContext
Example fix
// before
SecurityContext sc = ctx.getSecurityContext();
Set<String> roles = sc.getRoles(); // throws UnsupportedOperationException
// after
boolean isAdmin = ctx.getSecurityContext().isUserInRole("admin");
// or better: augment identity instead of overriding context
public class RolesAugmentor implements SecurityIdentityAugmentor {
public Uni<SecurityIdentity> augment(SecurityIdentity identity, SecurityIdentityAugmentationContext c) {
return Uni.createFrom().item(identity); // add roles here
}
} Defensive patterns
Strategy: fallback
Validate before calling
SecurityContext sc = ctx.getSecurityContext();
Set<String> roles;
try {
roles = sc.getRoles();
} catch (UnsupportedOperationException e) {
roles = Set.of(); // or derive from SecurityIdentity augmentors
}
if (roles.isEmpty() && sc.getUserPrincipal() != null) {
// use sc.isUserInRole(role) per expected role instead
} Type guard
boolean supportsGetRoles(SecurityContext sc) {
try { sc.getRoles(); return true; } catch (UnsupportedOperationException e) { return false; }
} Try / catch
try {
Set<String> roles = securityContext.getRoles();
} catch (UnsupportedOperationException e) {
// fall back to isUserInRole checks or SecurityIdentity.getRoles()
} Prevention
- Prefer SecurityIdentityAugmentor over replacing the SecurityContext via setSecurityContext()
- Use isUserInRole()/hasRole() instead of enumerating all roles
- In tests, assert filters do not override the context unless role enumeration is not needed
- Document on custom SecurityContext implementations whether getRoles() is supported
When it happens
Trigger: Calling SecurityContext.getRoles() (directly or via @RolesAllowed internal role gathering / SecurityIdentity.getRoles()) after a ContainerRequestFilter has called ContainerRequestContext.setSecurityContext() with a custom SecurityContext whose getRoles is not backed by a real role store.
Common situations: Custom auth filters that wrap or replace the security context; migrating code from classic RESTEasy where getRoles() worked; using quarkus-security APIs (e.g. isUserInRole-based annotations are fine, but role enumeration or programmatic SecurityIdentity.getRoles() fails); testing security filters that swap contexts.
Related errors
- retrieving all roles not supported when JAX-RS security cont
- Unsupported value type: %s
- Unable to fully read json value
- 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/d656c3addc1147fd.
Report an issue: GitHub.