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 '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.

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)

Solutions

  1. Remove the certificateToRolesMapper(...) call and keep attribute-based mapping
  2. Or remove rolesMapping()/certificateAttribute() and use only the custom mapper function
  3. 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

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

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/e65fb840bd899585. Report an issue: GitHub.