quarkusio/quarkus · error · IllegalArgumentException

Source role must not be null

Error message

Source role must not be null

What it means

The single-entry overload HttpSecurity.rolesMapping(String sourceRole, List<String> targetRoles) rejects a null source role with IllegalArgumentException before any mapping is built. The source role is the key of the mapping, so it must be a concrete non-null role name. After the null checks the method delegates to the Map-based rolesMapping, which applies the additional empty-value checks.

Source

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

            @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));
        }
        return rolesMapping(Map.of(sourceRole, targetRoles));
    }

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

    void addHttpPermissions(List<HttpPermissionCarrier> httpPermissions) {
        this.httpPermissions.addAll(httpPermissions);
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a non-null source role string; verify the variable is initialized before the call.
  2. If the role name comes from configuration, treat a missing value as 'skip this mapping' instead of calling rolesMapping.
  3. Use Objects.requireNonNull(sourceRole) at the call site with your own descriptive message to catch the problem earlier.

Example fix

// before
String source = config.sourceRole(); // may be null
httpSecurity.rolesMapping(source, List.of("admin"));
// after
if (config.sourceRole() != null) {
    httpSecurity.rolesMapping(config.sourceRole(), List.of("admin"));
}
Defensive patterns

Strategy: validation

Validate before calling

if (sourceRole != null) {
    httpSecurity.rolesMapping(sourceRole, targetRoles);
}

Type guard

static boolean hasSourceRole(String sourceRole) {
    return sourceRole != null && !sourceRole.isBlank();
}

Try / catch

try {
    httpSecurity.rolesMapping(source, targets);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("rolesMapping requires a source role: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: rolesMapping(null, List.of("admin")); passing a role variable that failed to resolve (e.g. a method returning the configured source role that was null in the current deployment); chaining from a config reader that yields null for a missing key.

Common situations: Programmatic security setup (HttpSecurity DSL in a recorder/observer) where the role name comes from optional configuration; refactoring that reordered initialization so a role-name field was still null; test code constructing mappings with placeholder nulls.

Related errors


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