apache/pulsar · error · IllegalArgumentException

Required configuration parameters: tlsCertFile, tlsKeyFile

Error message

Required configuration parameters: tlsCertFile, tlsKeyFile

What it means

When AuthenticationFactoryOAuth2's builder is configured with tokenEndpointAuthMethod = TLS_CLIENT_AUTH, the build() method requires the client's TLS certificate and key file paths. If either tlsCertFile or tlsKeyFile is blank, it throws this IllegalArgumentException because TLS client auth (mTLS) cannot authenticate without both.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2.java:324

        public Authentication build() {
            Flow flow;
            if (tokenEndpointAuthMethod == TokenEndpointAuthMethod.CLIENT_SECRET_POST) {
                flow = ClientCredentialsFlow.builder()
                        .issuerUrl(issuerUrl)
                        .privateKey(credentialsUrl == null ? null : credentialsUrl.toExternalForm())
                        .audience(audience)
                        .scope(scope)
                        .connectTimeout(connectTimeout)
                        .readTimeout(readTimeout)
                        .trustCertsFilePath(trustCertsFilePath)
                        .certFile(tlsCertFile)
                        .keyFile(tlsKeyFile)
                        .autoCertRefreshDuration(autoCertRefreshDuration)
                        .wellKnownMetadataPath(wellKnownMetadataPath)
                        .build();
            } else if (tokenEndpointAuthMethod == TokenEndpointAuthMethod.TLS_CLIENT_AUTH) {
                if (StringUtils.isBlank(tlsCertFile) || StringUtils.isBlank(tlsKeyFile)) {
                    throw new IllegalArgumentException("Required configuration parameters: tlsCertFile, tlsKeyFile");
                }
                flow = TlsClientAuthFlow.builder()
                        .issuerUrl(issuerUrl)
                        .clientId(clientId)
                        .certFile(tlsCertFile)
                        .keyFile(tlsKeyFile)
                        .audience(audience)
                        .scope(scope)
                        .connectTimeout(connectTimeout)
                        .readTimeout(readTimeout)
                        .trustCertsFilePath(trustCertsFilePath)
                        .wellKnownMetadataPath(wellKnownMetadataPath)
                        .autoCertRefreshDuration(autoCertRefreshDuration)
                        .build();
            } else {
                throw new IllegalArgumentException("Unsupported auth method: " + tokenEndpointAuthMethod);
            }
            return new AuthenticationOAuth2(flow, earlyTokenRefreshPercent, scheduler);

View on GitHub (pinned to 820761864e)

Solutions

  1. Call .tlsCertFile(path) and .tlsKeyFile(path) with valid paths before build().
  2. Verify the auth method is really TLS_CLIENT_AUTH; otherwise use client_secret_* and set issuerUrl/clientId/clientSecret instead.
  3. Check the env vars/properties feeding these values are set and non-blank.

Example fix

// before
Authentication auth = AuthenticationFactoryOAuth2.clientCredentials(builder)
    .issuerUrl(issuerUrl).clientId(id)
    .tokenEndpointAuthMethod(TokenEndpointAuthMethod.TLS_CLIENT_AUTH)
    .build(); // throws: no tlsCertFile/tlsKeyFile
// after
Authentication auth = AuthenticationFactoryOAuth2.clientCredentials(builder)
    .issuerUrl(issuerUrl).clientId(id)
    .tokenEndpointAuthMethod(TokenEndpointAuthMethod.TLS_CLIENT_AUTH)
    .tlsCertFile("/etc/pulsar/client-cert.pem")
    .tlsKeyFile("/etc/pulsar/client-key.pem")
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if (method == TokenEndpointAuthMethod.TLS_CLIENT_AUTH
        && (StringUtils.isBlank(tlsCertFile) || StringUtils.isBlank(tlsKeyFile))) {
    throw new IllegalStateException("TLS_CLIENT_AUTH requires both tlsCertFile and tlsKeyFile");
}
Authentication auth = builder...build();

Try / catch

try {
    return builder.build();
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("tlsCertFile")) {
        throw new ConfigurationException("Provide tlsCertFile and tlsKeyFile for tls_client_auth", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling build() after .tokenEndpointAuthMethod(TokenEndpointAuthMethod.TLS_CLIENT_AUTH) but without calling .tlsCertFile(...) and .tlsKeyFile(...) with non-blank paths.

Common situations: Switching auth method from client_secret_basic/post to TLS_CLIENT_AUTH and forgetting to add the mTLS fields; paths sourced from env vars that are unset/empty; using the string-based configure() path where keys are misnamed (e.g. 'certFile' instead of 'tlsCertFile').

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/00d89a6c9939d24d. Report an issue: GitHub.