quarkusio/quarkus · error · IllegalArgumentException

Roles cannot be null or empty

Error message

Roles cannot be null or empty

What it means

MTLS.Builder.rolesMapping(String, Set<String>) throws IllegalArgumentException when the roles set is null or empty. Each certificate attribute value must map to at least one role for the certificate-to-roles mapper to be meaningful.

Source

Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/security/MTLS.java:242

         * @see #rolesMapping(String, Set) for more information
         */
        public Builder rolesMapping(String certificateAttributeValue, String... roles) {
            return rolesMapping(certificateAttributeValue, Set.of(roles));
        }

        /**
         * Adds a certificate attribute value to roles mapping.
         * The certificate attribute itself can be configured with the {@link #certificateAttribute} method.
         *
         * @param certificateAttributeValue {@link AuthRuntimeConfig#certificateRoleAttribute()} values that will be
         *        mapped to the {@link SecurityIdentity} roles
         * @param roles {@link SecurityIdentity#getRoles()}
         * @return CertificateRolesBuilder
         */
        public Builder rolesMapping(String certificateAttributeValue, Set<String> roles) {
            Objects.requireNonNull(certificateAttributeValue);
            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");

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a non-empty Set of roles for each certificate attribute value
  2. Skip calling rolesMapping when no roles are available
  3. Fix the role source (config/lookup) to return actual role names

Example fix

// before
builder.rolesMapping("CN=admin", rolesFromConfig); // may be empty
// after
if (rolesFromConfig != null && !rolesFromConfig.isEmpty()) {
    builder.rolesMapping("CN=admin", rolesFromConfig);
}
Defensive patterns

Strategy: validation

Validate before calling

if (roles == null || roles.isEmpty()) {
    throw new IllegalStateException("rolesMapping requires at least one role for " + certAttrValue);
}
builder.rolesMapping(certAttrValue, roles);

Type guard

boolean hasRoles(Set<String> r) { return r != null && !r.isEmpty(); }

Prevention

When it happens

Trigger: Calling rolesMapping(attrValue, null) or rolesMapping(attrValue, Set.of()) — e.g. when the role list comes from empty config or a failed lookup.

Common situations: Empty roles config entry; a role-list parsing step that filtered everything out; DB/property lookup returning no roles for a certificate attribute.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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