quarkusio/quarkus · error · IllegalStateException
Roles mapping is already configured
Error message
Roles mapping is already configured
What it means
Each HttpSecurity instance allows exactly one roles mapping. HttpSecurity.rolesMapping(Map) checks an internal rolesMapping field and throws an IllegalStateException if it was already populated (either by a previous rolesMapping call or by addAuthRuntimeConfigToHttpSecurity). Role-to-roles merging is not supported at this level, so a second attempt fails.
Source
Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java:236
@Override
public HttpPermission put(String... paths) {
return path(paths).methods("PUT");
}
@Override
public HttpPermission post(String... paths) {
return path(paths).methods("POST");
}
@Override
public HttpPermission delete(String... paths) {
return path(paths).methods("DELETE");
}
@Override
public HttpSecurity rolesMapping(Map<String, List<String>> roleToRoles) {
if (rolesMapping != null) {
throw new IllegalStateException("Roles mapping is already configured");
}
if (roleToRoles == null || roleToRoles.isEmpty()) {
throw new IllegalArgumentException("Roles must not be empty");
}
roleToRoles.forEach(new BiConsumer<String, List<String>>() {
@Override
public void accept(String sourceRole, List<String> targetRoles) {
if (sourceRole.isEmpty()) {
throw new IllegalArgumentException("Source role must not be empty");
}
if (targetRoles == null || targetRoles.isEmpty()) {
throw new IllegalArgumentException("Target roles for role '%s' must not be empty".formatted(sourceRole));
}
}
});
this.rolesMapping = RolesMapping.of(roleToRoles);
return this;View on GitHub (pinned to e1c734241f)
Solutions
- Call rolesMapping only once per HttpSecurity instance; merge all role mappings into a single Map before the call.
- Chain carefully: note rolesMapping throws by design when re-entered — remove the second call rather than chaining it again.
- If multiple sources provide mappings, combine them into one map first and pass the merged result.
Example fix
// before
httpSecurity.rolesMapping(Map.of("admin", List.of("manager")));
httpSecurity.rolesMapping(Map.of("user", List.of("viewer"))); // throws
// after
Map<String, List<String>> merged = new HashMap<>();
merged.put("admin", List.of("manager"));
merged.put("user", List.of("viewer"));
httpSecurity.rolesMapping(merged); Defensive patterns
Strategy: validation
Validate before calling
// merge all role mappings into ONE map and call rolesMapping exactly once Map<String, List<String>> merged = new HashMap<>(); merged.putAll(sourceAMappings); merged.putAll(sourceBMappings); httpSecurity.rolesMapping(merged);
Try / catch
try {
httpSecurity.rolesMapping(mapping);
} catch (IllegalStateException e) {
if (e.getMessage().contains("Roles mapping is already configured")) {
log.warn("Roles mapping already applied; merging into existing configuration instead");
} else {
throw e;
}
} Prevention
- Call rolesMapping exactly once per HttpSecurity instance — never chain it.
- Consolidate role mappings from all sources into one map before applying.
- Watch for setup helpers that can run twice (dev reload, multiple initializers) and make them idempotent.
When it happens
Trigger: Calling httpSecurity.rolesMapping(...) twice on the same HttpSecurity instance, or calling it after addAuthRuntimeConfigToHttpSecurity already populated the mapping.
Common situations: Security setup helpers invoked multiple times (e.g. in different lifecycle phases or dev-mode reload); two libraries/initializers both applying roles mapping to the same builder; chained rolesMapping(...) calls in a fluent setup.
Related errors
- CSRF must not be null
- Cannot configure form-based authentication programmatically
- Cannot configure basic authentication programmatically becau
- TLS client authentication has already been enabled with this
- Cannot configure TLS configuration name programmatically bec
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/e9acdddf4e789b8b.
Report an issue: GitHub.