quarkusio/quarkus · error · IllegalStateException
The certificate to roles mapper is already configured with t
Error message
The certificate to roles mapper is already configured with the 'certificateToRolesMapper' method
What it means
MTLS.Builder supports two mutually exclusive ways to map client certificates to SecurityIdentity roles: attribute-based role mapping via rolesMapping/certificateAttribute, or a custom function via certificateToRolesMapper. This IllegalStateException is thrown from assertCertificateToRolesMapperNotSetYet when a builder already had the custom mapper set and you then attempt to configure the attribute/roles-mapping path. Only one strategy may be configured per builder.
Source
Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/security/MTLS.java:259
if (roles == null || roles.isEmpty()) {
throw new IllegalArgumentException("Roles cannot be null or empty");
}
assertCertificateToRolesMapperNotSetYet();
if (certificateAttributeValueToRoles == null) {
certificateAttributeValueToRoles = new HashMap<>();
}
certificateAttributeValueToRoles.computeIfAbsent(certificateAttributeValue, new Function<String, Set<String>>() {
@Override
public Set<String> apply(String ignored) {
return new HashSet<>();
}
}).addAll(roles);
return this;
}
private void assertCertificateToRolesMapperNotSetYet() {
if (certificateToRolesMapper != null) {
throw new IllegalStateException(
"The certificate to roles mapper is already configured with the 'certificateToRolesMapper' method");
}
}
/**
* Check the values of different client certificate attributes and map them to the {@link SecurityIdentity} roles.
*
* @param certificateToRolesMapper a client certificate to the {@link SecurityIdentity} roles mapper
* @return Builder
*/
public Builder certificateToRolesMapper(Function<X509Certificate, Set<String>> certificateToRolesMapper) {
if (certificateAttributeValueToRoles != null) {
throw new IllegalStateException(
"The certificate to roles mapper is already configured with the 'rolesMapping' method");
}
assertCertificateToRolesMapperNotSetYet();
this.certificateToRolesMapper = certificateToRolesMapper;
return this;View on GitHub (pinned to e1c734241f)
Solutions
- Pick one strategy: remove the certificateToRolesMapper(...) call if you want attribute-based rolesMapping/certificateAttribute
- Or remove the rolesMapping/certificateAttribute call and keep only the custom certificateToRolesMapper function
- If both behaviors are needed, implement the attribute-based logic inside the single certificateToRolesMapper function
Example fix
// before
mtls.certificateToRolesMapper(cert -> Set.of("admin"))
.certificateAttribute("CN"); // IllegalStateException
// after
mtls.certificateToRolesMapper(cert -> {
String cn = ...; // fold attribute logic into the mapper
return Set.of("admin");
}); Defensive patterns
Strategy: validation
Validate before calling
if (builderMapperSet && wantAttributeMapping) { throw new IllegalArgumentException("choose either certificateToRolesMapper or rolesMapping, not both"); } Try / catch
try { mtls.certificateAttribute("CN"); } catch (IllegalStateException e) { log.warn("Mapper already configured; keeping certificateToRolesMapper"); } Prevention
- Configure mTLS role mapping in exactly one place in your security setup
- Search your HttpSecurity builder chain for both mapping methods before adding a new one
- Centralize mTLS builder construction in a single producer/CDI method
When it happens
Trigger: Calling MTLS.Builder.certificateAttribute(...) or rolesMapping(...) after certificateToRolesMapper(Function<X509Certificate, Set<String>>) has already been invoked on the same Builder instance.
Common situations: Programmatically building HttpSecurity with mTLS auth where code paths merge — e.g. default configuration sets a custom mapper and then an extension or user code adds rolesMapping; copy-pasted builder chains that configure both mechanisms.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- The certificate to roles mapper is already configured with t
- TLS configuration is already set
- TLS configuration name has already been configured with the
- No producers for required item %s, step builder used: %s
- cycle detection failure report (dynamic CycleBuildException
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/92a7dcac41a645f0.
Report an issue: GitHub.