quarkusio/quarkus · error · IllegalArgumentException

Source role must not be empty

Error message

Source role must not be empty

What it means

Inside HttpSecurityImpl.rolesMapping(Map), each map entry is validated by the anonymous BiConsumer; a source role that is the empty string ("") is rejected with IllegalArgumentException. A source role names the role the incoming identity must hold, so an empty name cannot be matched against any identity. The check runs per entry during forEach, before RolesMapping.of is built.

Source

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

    @Override
    public HttpPermission delete(String... paths) {
        return path(paths).methods("DELETE");
    }

    @Override
    public HttpSecurity rolesMapping(Map<String, List<String>> roleToRoles) {
        if (rolesMapping != null) {
            throw new IllegalStateException("Roles mapping is already configured");
        }
        if (roleToRoles == null || roleToRoles.isEmpty()) {
            throw new IllegalArgumentException("Roles must not be empty");
        }
        roleToRoles.forEach(new BiConsumer<String, List<String>>() {
            @Override
            public void accept(String sourceRole, List<String> targetRoles) {
                if (sourceRole.isEmpty()) {
                    throw new IllegalArgumentException("Source role must not be empty");
                }
                if (targetRoles == null || targetRoles.isEmpty()) {
                    throw new IllegalArgumentException("Target roles for role '%s' must not be empty".formatted(sourceRole));
                }
            }
        });

        this.rolesMapping = RolesMapping.of(roleToRoles);
        return this;
    }

    @Override
    public HttpSecurity rolesMapping(String sourceRole, List<String> targetRoles) {
        if (sourceRole == null) {
            throw new IllegalArgumentException("Source role must not be null");
        }
        if (targetRoles == null) {
            throw new IllegalArgumentException("Target roles for role '%s' must not be null".formatted(sourceRole));

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove empty-string keys from the map before calling rolesMapping (filter entries with !sourceRole.isBlank()).
  2. Fix the config/data source so the source role name is present (e.g. correct the property key in application.properties).
  3. Add your own up-front validation to fail with a clearer message naming where the blank role came from.

Example fix

// before
Map<String, List<String>> mapping = parse(rawMappings); // may contain ""
httpSecurity.rolesMapping(mapping);
// after
Map<String, List<String>> mapping = rawMappings.entrySet().stream()
    .filter(e -> !e.getKey().isBlank())
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
httpSecurity.rolesMapping(mapping);
Defensive patterns

Strategy: validation

Validate before calling

boolean allRolesNamed = roleToRoles.keySet().stream().noneMatch(k -> k.isBlank());
if (allRolesNamed) {
    httpSecurity.rolesMapping(roleToRoles);
}

Type guard

static boolean isValidRoleMapping(Map<String, List<String>> m) {
    return m != null && m.entrySet().stream().allMatch(e ->
        e.getKey() != null && !e.getKey().isBlank()
        && e.getValue() != null && !e.getValue().isEmpty());
}

Try / catch

try {
    httpSecurity.rolesMapping(mapping);
} catch (IllegalArgumentException e) {
    throw new ConfigurationException("Invalid source role in mapping: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: rolesMapping(Map.of("", List.of("admin"))); building the map from split config strings where an empty key survived (e.g. "=admin" in a property value); a data-driven mapping file containing a blank role name.

Common situations: Parsing role mappings from application.properties where the key before '=' was omitted; user-supplied mapping files with blank lines parsed into empty keys; case-splitting a composite key like "source:target" where the source portion was empty.

Related errors


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