quarkusio/quarkus · error · IllegalArgumentException

Invalid username: " + usernameHeader

Error message

Invalid username: " + usernameHeader

What it means

IllegalArgumentException thrown by JdbcPermissionChecker.hasAdminRole(), a @PermissionChecker used for @PermissionAction-based authorization. The username header supplied to the permission check is not one of the recognized values ("admin" or "user"), so the switch's default arm rejects it. It guards against arbitrary/unexpected header values reaching the SQL lookup.

Source

Thrown at integration-tests/elytron-security-jdbc/src/main/java/io/quarkus/elytron/security/jdbc/it/JdbcPermissionChecker.java:27

import jakarta.inject.Inject;
import jakarta.transaction.Transactional;

import io.agroal.api.AgroalDataSource;
import io.quarkus.security.PermissionChecker;

@ApplicationScoped
public class JdbcPermissionChecker {

    @Inject
    AgroalDataSource defaultDataSource;

    @Transactional
    @PermissionChecker("admin-role-in-db")
    boolean hasAdminRole(String usernameHeader) {
        String username = switch (usernameHeader) {
            case "admin" -> "admin";
            case "user" -> "user";
            default -> throw new IllegalArgumentException("Invalid username: " + usernameHeader);
        };
        try (Connection connection = defaultDataSource.getConnection(); Statement stat = connection.createStatement()) {
            try (ResultSet roleQuery = stat
                    .executeQuery("select u.role from test_user u where u.username='" + username + "'")) {
                if (!roleQuery.first()) {
                    throw new IllegalStateException("Username '%s' not in the 'test_user' table".formatted(username));
                }
                var role = roleQuery.getString(1);
                return "admin".equals(role);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Send the expected username header value ("admin" or "user") with the request
  2. Extend the switch to handle additional valid usernames if the test adds users
  3. Null-check/normalize (trim) the header value before the switch
  4. Check header name casing and any proxy stripping of custom headers

Example fix

// before
default -> throw new IllegalArgumentException("Invalid username: " + usernameHeader);
// after
if (usernameHeader == null) {
    throw new IllegalArgumentException("Missing username header");
}
String normalized = usernameHeader.trim();
default -> throw new IllegalArgumentException("Invalid username: " + normalized);
Defensive patterns

Strategy: validation

Validate before calling

if (usernameHeader == null || !(usernameHeader.equals("admin") || usernameHeader.equals("user"))) {
    throw new BadRequestException("username header must be 'admin' or 'user'");
}

Type guard

boolean isValidUsername(String u) {
    return "admin".equals(u) || "user".equals(u);
}

Try / catch

try {
    return checkPermission(header);
} catch (IllegalArgumentException e) {
    throw new ForbiddenException(e.getMessage());
}

Prevention

When it happens

Trigger: Request supplies a usernameHeader value other than "admin" or "user" (or no header at all, making it null), causing the switch default to throw before the JDBC query runs.

Common situations: Test client forgetting to set the username header; header spelled differently or with whitespace/case mismatch; new expected users not added to the switch; header consumed by a proxy.

Related errors


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