quarkusio/quarkus · error · IllegalArgumentException
Authentication has already been set
Error message
Authentication has already been set
What it means
Thrown by HttpPermission's validateAuthenticationNotSetYet when the authentication mechanism is configured twice. A permission can define at most one authentication setup; once authMechanism is non-null, a second authentication assignment is rejected so the resulting policy is never ambiguous.
Source
Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java:398
this.authMechanism = null;
this.authorizationPolicy = null;
this.shared = false;
this.methods = null;
this.applyToJaxRs = false;
}
private void requireAuthenticationByDefault() {
// if someone selects authentication mechanism and doesn't configure
// authorization policy, it is reasonable to expect they require authentication
// similarly to what we do with @BasicAuthentication etc.
if (authorizationPolicy == null) {
authenticated();
}
}
private void validateAuthenticationNotSetYet() {
if (authMechanism != null) {
throw new IllegalArgumentException("Authentication has already been set");
}
}
private void validateAuthorizationNotSetYet() {
if (authMechanism == null && authorizationPolicy != null) {
throw new IllegalArgumentException("Authorization has already been set");
}
}
@Override
public HttpPermission basic() {
return authenticatedWith(BasicAuthentication.AUTH_MECHANISM_SCHEME);
}
@Override
public HttpPermission form() {
return authenticatedWith(FormAuthentication.AUTH_MECHANISM_SCHEME);
}View on GitHub (pinned to e1c734241f)
Solutions
- Call only one authentication method per HttpPermission; remove the redundant authenticated()/authenticatedWith(...) call.
- If multiple mechanisms should be allowed, use authenticatedWith(Set<String> schemes) once with all schemes instead of repeated calls.
- Split into separate permissions (separate paths() calls) if different paths need different mechanisms.
Example fix
// before
httpSecurity.paths("/api/*").basic().bearer(); // throws
// after
httpSecurity.paths("/api/*").authenticatedWith(Set.of("basic", "Bearer")); Defensive patterns
Strategy: validation
Validate before calling
// ensure only one auth call: track in a local builder wrapper
boolean authSet = false;
if (authSet) throw new IllegalStateException("auth already configured"); Try / catch
try { perm.authenticatedWith(mech); } catch (IllegalArgumentException e) { if (!e.getMessage().contains("Authentication has already been set")) throw e; } Prevention
- Call exactly one of authenticated()/authenticatedWith(...)/basic()/form()/bearer()/mTLS()/webAuthn() per permission.
- Use authenticatedWith(Set<String>) to allow multiple schemes in one call.
- Decide the authentication mechanism before building the chain.
When it happens
Trigger: Calling authenticatedWith(...) twice, or authenticated() followed by authenticatedWith(...)/basic()/form()/bearer()/mTLS()/webAuthn()/authorizationCodeFlow() on the same HttpPermission instance.
Common situations: Chaining .basic().bearer() hoping to allow multiple mechanisms; conditional code that calls different auth methods on the same permission object; copy-paste refactors of fluent chains.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Policy has already been set
- Authorization has already been set
- Authentication mechanism must not be null or blank
- Authentication mechanism must not be null or emptz
- No IdentityProviders were registered to handle Authenticatio
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4dc813cd97f5a447.
Report an issue: GitHub.