quarkusio/quarkus · error · IllegalStateException
The certificate to roles mapper is already configured with…
Error message
The certificate to roles mapper is already configured with the 'rolesMapping' method
What it means
The inverse guard of MTLS.Builder: certificateToRolesMapper(Function) throws IllegalStateException when rolesMapping-based mapping (certificateAttributeValueToRoles) was already configured. The builder allows only one certificate-to-roles mapping mechanism at a time.
Solutions
- Remove the certificateToRolesMapper(...) call and keep attribute-based mapping
- Or remove rolesMapping()/certificateAttribute() and use only the custom mapper function
- Encode attribute rules inside the single certificateToRolesMapper function if both are required
Example fix
// before
mtls.rolesMapping(Map.of("CN=acme", Set.of("user")))
.certificateToRolesMapper(cert -> Set.of("admin")); // IllegalStateException
// after
mtls.rolesMapping(Map.of("CN=acme", Set.of("user"))); Defensive patterns
Strategy: validation
Validate before calling
if (attributeMappingConfigured) { /* do not call certificateToRolesMapper */ } Try / catch
try { mtls.certificateToRolesMapper(fn); } catch (IllegalStateException e) { log.warn("rolesMapping already configured; ignoring custom mapper"); } Prevention
- Decide once between attribute-based mapping and a custom mapper function
- Keep MTLS.Builder construction in one code path, not spread across config and code
- Document which mechanism your application uses
When it happens
Trigger: Calling MTLS.Builder.certificateToRolesMapper(...) after certificateAttribute(...) or rolesMapping(...) has already populated certificateAttributeValueToRoles on the same builder.
Common situations: Composing mTLS configuration from multiple sources (application config plus code) where attribute mapping is set up first and a custom mapper is then added; refactored security setup that chained both methods.
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…
- TLS configuration is already set
- TLS configuration name has already been configured with the…
- Access token does not contain a confirmation 'cnf' claim…
- Already closed
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/e65fb840bd899585.
Report an issue: GitHub.
Appendix: source
Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/security/MTLS.java:272
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;
}
/**
* Mutual TLS authentication mechanism priority.
*
* @param priority {@link MtlsAuthenticationMechanism#getPriority()}
* @return Builder
* @see AuthRuntimeConfig#mTlsPriority()
*/
public Builder priority(int priority) {
this.priority = Optional.of(priority);
return this;
}View on GitHub (pinned to e1c734241f)