{"record":{"id":"00d89a6c9939d24d","repo":"apache/pulsar","slug":"required-configuration-parameters-tlscertfile-tl","errorCode":null,"errorMessage":"Required configuration parameters: tlsCertFile, tlsKeyFile","messagePattern":"Required configuration parameters: tlsCertFile, tlsKeyFile","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2.java","lineNumber":324,"sourceCode":"        public Authentication build() {\n            Flow flow;\n            if (tokenEndpointAuthMethod == TokenEndpointAuthMethod.CLIENT_SECRET_POST) {\n                flow = ClientCredentialsFlow.builder()\n                        .issuerUrl(issuerUrl)\n                        .privateKey(credentialsUrl == null ? null : credentialsUrl.toExternalForm())\n                        .audience(audience)\n                        .scope(scope)\n                        .connectTimeout(connectTimeout)\n                        .readTimeout(readTimeout)\n                        .trustCertsFilePath(trustCertsFilePath)\n                        .certFile(tlsCertFile)\n                        .keyFile(tlsKeyFile)\n                        .autoCertRefreshDuration(autoCertRefreshDuration)\n                        .wellKnownMetadataPath(wellKnownMetadataPath)\n                        .build();\n            } else if (tokenEndpointAuthMethod == TokenEndpointAuthMethod.TLS_CLIENT_AUTH) {\n                if (StringUtils.isBlank(tlsCertFile) || StringUtils.isBlank(tlsKeyFile)) {\n                    throw new IllegalArgumentException(\"Required configuration parameters: tlsCertFile, tlsKeyFile\");\n                }\n                flow = TlsClientAuthFlow.builder()\n                        .issuerUrl(issuerUrl)\n                        .clientId(clientId)\n                        .certFile(tlsCertFile)\n                        .keyFile(tlsKeyFile)\n                        .audience(audience)\n                        .scope(scope)\n                        .connectTimeout(connectTimeout)\n                        .readTimeout(readTimeout)\n                        .trustCertsFilePath(trustCertsFilePath)\n                        .wellKnownMetadataPath(wellKnownMetadataPath)\n                        .autoCertRefreshDuration(autoCertRefreshDuration)\n                        .build();\n            } else {\n                throw new IllegalArgumentException(\"Unsupported auth method: \" + tokenEndpointAuthMethod);\n            }\n            return new AuthenticationOAuth2(flow, earlyTokenRefreshPercent, scheduler);","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/AuthenticationFactoryOAuth2.java#L306-L342","documentation":"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.","triggerScenarios":"Calling build() after .tokenEndpointAuthMethod(TokenEndpointAuthMethod.TLS_CLIENT_AUTH) but without calling .tlsCertFile(...) and .tlsKeyFile(...) with non-blank paths.","commonSituations":"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').","solutions":["Call .tlsCertFile(path) and .tlsKeyFile(path) with valid paths before build().","Verify the auth method is really TLS_CLIENT_AUTH; otherwise use client_secret_* and set issuerUrl/clientId/clientSecret instead.","Check the env vars/properties feeding these values are set and non-blank."],"exampleFix":"// before\nAuthentication auth = AuthenticationFactoryOAuth2.clientCredentials(builder)\n    .issuerUrl(issuerUrl).clientId(id)\n    .tokenEndpointAuthMethod(TokenEndpointAuthMethod.TLS_CLIENT_AUTH)\n    .build(); // throws: no tlsCertFile/tlsKeyFile\n// after\nAuthentication auth = AuthenticationFactoryOAuth2.clientCredentials(builder)\n    .issuerUrl(issuerUrl).clientId(id)\n    .tokenEndpointAuthMethod(TokenEndpointAuthMethod.TLS_CLIENT_AUTH)\n    .tlsCertFile(\"/etc/pulsar/client-cert.pem\")\n    .tlsKeyFile(\"/etc/pulsar/client-key.pem\")\n    .build();","handlingStrategy":"validation","validationCode":"if (method == TokenEndpointAuthMethod.TLS_CLIENT_AUTH\n        && (StringUtils.isBlank(tlsCertFile) || StringUtils.isBlank(tlsKeyFile))) {\n    throw new IllegalStateException(\"TLS_CLIENT_AUTH requires both tlsCertFile and tlsKeyFile\");\n}\nAuthentication auth = builder...build();","typeGuard":null,"tryCatchPattern":"try {\n    return builder.build();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"tlsCertFile\")) {\n        throw new ConfigurationException(\"Provide tlsCertFile and tlsKeyFile for tls_client_auth\", e);\n    }\n    throw e;\n}","preventionTips":["When selecting TLS_CLIENT_AUTH, set the cert/key files in the same code block.","Check env vars feeding these paths are set and non-blank.","Verify key names in the params JSON match tlsCertFile/tlsKeyFile exactly."],"tags":["pulsar-client","oauth2","mtls","configuration"],"backgroundTag":"missing-required-config-parameter","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}