quarkusio/quarkus · error · IllegalArgumentException

Client authentication cannot be disabled with this API

Error message

Client authentication cannot be disabled with this API

What it means

The programmatic HttpSecurity.mTLS() API only supports enabling TLS client authentication (REQUIRED or REQUEST). Passing ClientAuth.NONE would attempt to disable mTLS through an API designed only to enable it, which Quarkus explicitly forbids with an IllegalArgumentException. Disabling belongs to configuration (quarkus.http.ssl.client-auth=NONE, the default).

Source

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

    @Override
    public HttpSecurity mTLS(String tlsConfigurationName, TlsConfiguration tlsConfiguration) {
        return mechanism(MTLS.required(tlsConfigurationName, tlsConfiguration));
    }

    @Override
    public HttpSecurity mTLS(MtlsAuthenticationMechanism mTLSAuthenticationMechanism) {
        return mechanism(mTLSAuthenticationMechanism);
    }

    @Override
    public HttpSecurity mTLS(ClientAuth tlsClientAuth) {
        if (tlsClientAuth == null) {
            throw new IllegalArgumentException("Client authentication cannot be null");
        }
        return switch (tlsClientAuth) {
            case REQUIRED -> mechanism(MTLS.required());
            case REQUEST -> mechanism(MTLS.request());
            case NONE -> throw new IllegalArgumentException("Client authentication cannot be disabled with this API");
        };
    }

    @Override
    public HttpPermission path(String... patterns) {
        if (patterns == null || patterns.length == 0) {
            throw new IllegalArgumentException("Paths must not be empty");
        }
        var httpPermission = new HttpPermissionImpl(patterns);
        httpPermissions.add(httpPermission);
        return httpPermission;
    }

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

View on GitHub (pinned to e1c734241f)

Solutions

  1. Only call mTLS() for REQUIRED or REQUEST; skip the call when the desired value is NONE.
  2. Handle NONE by relying on the default configuration (no client auth) instead of the API.
  3. Filter dynamic input: if (auth != ClientAuth.NONE) httpSecurity.mTLS(auth);

Example fix

// before
httpSecurity.mTLS(ClientAuth.NONE); // throws
// after
if (desiredAuth != ClientAuth.NONE) {
    httpSecurity.mTLS(desiredAuth);
} // NONE: do nothing, it is the default
Defensive patterns

Strategy: validation

Validate before calling

if (clientAuth != null && clientAuth != ClientAuth.NONE) {
    httpSecurity.mTLS(clientAuth);
} // NONE: skip; disabled is the default state

Type guard

boolean canEnableMtls(ClientAuth auth) {
    return auth == ClientAuth.REQUIRED || auth == ClientAuth.REQUEST;
}

Try / catch

try {
    httpSecurity.mTLS(clientAuth);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("cannot be disabled")) {
        log.warn("ClientAuth.NONE is not supported by mTLS(); ignoring (already disabled by default)");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling httpSecurity.mTLS(ClientAuth.NONE), often when the ClientAuth value comes from a config enum or switch that includes NONE as a possible case.

Common situations: Applications mapping quarkus.http.ssl.client-auth values directly into the programmatic API without filtering out NONE; generic security-setup code iterating all ClientAuth values.

Understand the failure class

Related errors


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