quarkusio/quarkus · error · IllegalArgumentException
TLS client authentication has already been enabled with this
Error message
TLS client authentication has already been enabled with this API or with the 'quarkus.http.ssl.client-auth' configuration property
What it means
When an MtlsAuthenticationMechanism is registered via mechanism(), Quarkus checks whether TLS client authentication (clientAuth) is already enabled either by a previous programmatic mTLS call or by the quarkus.http.ssl.client-auth property. Since merging/overriding mTLS configuration is not supported, a second enabling attempt throws an IllegalArgumentException.
Source
Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java:139
final FormAuthConfig actualConfig = vertxHttpConfig.auth().form();
if (!actualConfig.equals(defaults)) {
throw new IllegalArgumentException("Cannot configure form-based authentication programmatically "
+ "because it has already been configured in the 'application.properties' file");
}
} else if (mechanism.getClass() == BasicAuthenticationMechanism.class) {
String actualRealm = vertxHttpConfig.auth().realm().orElse(null);
if (actualRealm != null) {
throw new IllegalArgumentException("Cannot configure basic authentication programmatically because "
+ "the authentication realm has already been configured in the 'application.properties' file");
}
} else if (mechanism.getClass() == MtlsAuthenticationMechanism.class) {
boolean mTlsEnabled = !ClientAuth.NONE.equals(clientAuth);
if (mTlsEnabled) {
// current we do not allow "merging" (or overriding) of the configuration provided in application.properties
// there shouldn't be a technical issue allowing that, but that's the behavior we have for other mechanisms
// as well, so this method only allows to "enable" mTLS, never disable or change configuration provided
// properties file
throw new IllegalArgumentException("TLS client authentication has already been enabled with this API or"
+ " with the 'quarkus.http.ssl.client-auth' configuration property");
}
var mTLS = ((MtlsAuthenticationMechanism) mechanism);
clientAuth = mTLS.getTlsClientAuth();
if (mTLS.getHttpServerTlsConfigName().isPresent()) {
if (httpServerTlsConfigName.isPresent()) {
throw new IllegalArgumentException("Cannot configure TLS configuration name programmatically because it "
+ " has already been configured with the 'quarkus.http.tls-configuration-name' configuration property");
}
httpServerTlsConfigName = mTLS.getHttpServerTlsConfigName();
if (mTLS.getInitialTlsConfiguration() != null) {
TlsConfigurationRegistry tlsConfigurationRegistry = Arc.container().instance(TlsConfigurationRegistry.class)
.get();
if (tlsConfigurationRegistry.get(httpServerTlsConfigName.get()).isPresent()) {
throw new IllegalArgumentException(("Cannot register the TLS configuration '%s' in the TLS "
+ "Configuration registry because configuration with this name has already"
+ " been registered").formatted(httpServerTlsConfigName.get()));
}View on GitHub (pinned to e1c734241f)
Solutions
- Remove quarkus.http.ssl.client-auth from application.properties and configure mTLS only programmatically.
- Register the mTLS mechanism exactly once; search the codebase for duplicated mTLS()/mechanism() calls.
- Keep mTLS solely in application.properties and delete the programmatic registration.
Example fix
// before (application.properties) quarkus.http.ssl.client-auth=REQUIRED // code: httpSecurity.mTLS(ClientAuth.REQUIRED) // throws // after: remove the property, then configure once in code httpSecurity.mTLS(ClientAuth.REQUIRED);
Defensive patterns
Strategy: validation
Validate before calling
// ensure quarkus.http.ssl.client-auth is unset before programmatic mTLS
// ConfigProvider.getConfig().getOptionalValue("quarkus.http.ssl.client-auth", String.class)
// .ifPresent(v -> { throw new IllegalStateException("ssl.client-auth already set in properties"); });
httpSecurity.mTLS(ClientAuth.REQUIRED); // call exactly once Try / catch
try {
httpSecurity.mTLS(ClientAuth.REQUIRED);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("TLS client authentication has already been enabled")) {
log.warn("mTLS already enabled via properties or a prior call; skipping");
} else {
throw e;
}
} Prevention
- Register the mTLS mechanism exactly once — centralize it in a single setup method.
- Remove quarkus.http.ssl.client-auth when enabling mTLS programmatically.
- Guard idempotency if setup code can run more than once (dev-mode restarts, multiple initializers).
When it happens
Trigger: Calling httpSecurity.mTLS(...) or mechanism(new MtlsAuthenticationMechanism(...)) more than once, or calling it after quarkus.http.ssl.client-auth is set to REQUIRED/REQUEST in application.properties.
Common situations: Migrating mTLS from properties-based config to the programmatic API while the property remains set; duplicate registration of the same mechanism in a security setup helper that is invoked twice.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Cannot configure TLS configuration name programmatically bec
- Client authentication cannot be disabled with this API
- TLS client authentication is not available, please enable it
- Cannot configure form-based authentication programmatically
- Cannot configure basic authentication programmatically becau
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/7da72cb12810822f.
Report an issue: GitHub.