quarkusio/quarkus · error · IllegalArgumentException

Role to roles mapping must not be null

Error message

Role to roles mapping must not be null

What it means

In the same roles(Map, String...) method, after the roles array is validated, a null roleToRoles map is rejected with IllegalArgumentException. Unlike the standalone rolesMapping method (which tolerates being skipped entirely), when you call this overload the mapping map itself is an explicit argument and must be non-null; it is handed directly to RolesAllowedHttpSecurityPolicy. An empty map appears to be accepted here - only null is rejected.

Source

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

            this.policy = new Policy(PermitSecurityPolicy.NAME, null);
            return HttpSecurityImpl.this;
        }

        @Override
        public HttpSecurity deny() {
            validatePolicyNotSetYet();
            this.policy = new Policy(DenySecurityPolicy.NAME, null);
            return HttpSecurityImpl.this;
        }

        @Override
        public HttpSecurity roles(Map<String, List<String>> roleToRoles, String... roles) {
            validatePolicyNotSetYet();
            if (roles == null || roles.length == 0) {
                throw new IllegalArgumentException("Roles must not be empty");
            }
            if (roleToRoles == null) {
                throw new IllegalArgumentException("Role to roles mapping must not be null");
            }
            this.policy = new Policy(null, new RolesAllowedHttpSecurityPolicy(Arrays.asList(roles), null, roleToRoles));
            return HttpSecurityImpl.this;
        }

        @Override
        public HttpSecurity roles(String... roles) {
            return roles(Map.of(), roles);
        }

        @Override
        public HttpSecurity permissions(Permission... permissions) {
            validatePolicyNotSetYet();
            if (permissions == null || permissions.length == 0) {
                throw new IllegalArgumentException("Permissions must not be empty");
            }
            policy = new Policy(null, new PermissionsHttpSecurityPolicy(permissions));
            return HttpSecurityImpl.this;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass an explicit empty map (Map.of()) when there is no mapping, or use the roles-only overload if available.
  2. Initialize the mapping variable to Map.of() by default rather than null.
  3. Null-check the mapping source and substitute Map.of() at the call site.

Example fix

// before
httpSecurity.path("/api/*").roles(mapping, "admin"); // mapping may be null
// after
Map<String, List<String>> safeMapping =
    mapping != null ? mapping : Map.of();
httpSecurity.path("/api/*").roles(safeMapping, "admin");
Defensive patterns

Strategy: validation

Validate before calling

Map<String, List<String>> safeMapping =
    roleToRoles != null ? roleToRoles : Map.of();
httpSecurity.path(path).roles(safeMapping, roles);

Type guard

static <K, V> Map<K, V> orEmpty(Map<K, V> m) {
    return m != null ? m : Map.of();
}

Try / catch

try {
    httpSecurity.path("/api/*").roles(mapping, "admin");
} catch (IllegalArgumentException e) {
    log.error("roles() requires a non-null mapping: " + e.getMessage());
}

Prevention

When it happens

Trigger: httpSecurity.path("/x").roles(null, "admin"); forwarding an uninitialized Map field; a lookup method returning null when no mapping exists for the path.

Common situations: Programmatic security setup where role-to-roles mapping is optional but the overload requires an explicit value; refactoring from the mapping-free overload and passing null instead of Map.of(); deserialization of a mapping object that was absent.

Related errors


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