{"record":{"id":"685f1f196ec90513","repo":"apache/pulsar","slug":"failed-to-resolve-the-admin-client-tls-factory","errorCode":null,"errorMessage":"Failed to resolve the admin client TLS factory","messagePattern":"Failed to resolve the admin client TLS factory","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnectorProvider.java","lineNumber":117,"sourceCode":"    synchronized TlsFactoryOwnership sharedTlsFactory() {\n        if (sharedTlsFactory != null) {\n            // Already resolved. The connectors borrow it: this provider stays the owner.\n            return TlsFactoryOwnership.borrowing(sharedTlsFactory.factory());\n        }\n        if (!AsyncHttpConnector.needsTlsFactory(conf)) {\n            sharedTlsFactory = TlsFactoryOwnership.none();\n            return sharedTlsFactory;\n        }\n        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(\n                new DefaultThreadFactory(\"pulsar-admin-tls-factory\"));\n        try {\n            sharedTlsFactory = TlsFactoryOwnership.owning(\n                    ClientTlsFactorySupport.resolveClientTlsFactory(conf, executor, executor,\n                            conf.getOpenTelemetry()),\n                    executor);\n        } catch (Exception e) {\n            executor.shutdownNow();\n            throw new RuntimeException(\"Failed to resolve the admin client TLS factory\", e);\n        }\n        return TlsFactoryOwnership.borrowing(sharedTlsFactory.factory());\n    }\n\n    /**\n     * Release the shared TLS factory and the executor driving its rotation. Called when the owning\n     * {@code PulsarAdmin} closes; the connectors borrowed the factory and dispose only their own\n     * subscriptions.\n     */\n    public synchronized void close() {\n        if (sharedTlsFactory == null) {\n            return;\n        }\n        sharedTlsFactory.close();\n        sharedTlsFactory = TlsFactoryOwnership.none();\n    }\n\n    @VisibleForTesting","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/http/AsyncHttpConnectorProvider.java#L99-L135","documentation":"RuntimeException thrown when the shared PulsarTlsFactory for an admin client cannot be resolved via ClientTlsFactorySupport.resolveClientTlsFactory. The connector provider lazily creates one shared TLS factory plus an executor; any exception during resolution (bad TLS key/cert paths, keystore problems) shuts the executor down and aborts admin client creation.","triggerScenarios":"Building a PulsarAdmin over https (or with TLS auth configured) where TLS key/certificate files are missing, unreadable, malformed, or the configured PulsarTlsFactory initialization throws.","commonSituations":"Typo in tlsKeyFilePath/tlsCertificateFilePath; files not readable by the process user; password-protected keystore without provided password; enabling TLS auth (tlsAuthenticationEnabled) without supplying key/cert files.","solutions":["Check the wrapped cause (e.getCause()) for the concrete TLS resolution failure.","Verify tlsCertificateFilePath and tlsKeyFilePath point to valid, readable PEM/keystore files.","Ensure the TLS trust store (tlsTrustCertsFilePath or default CA) is valid.","If TLS auth is enabled, confirm both client key and certificate files are configured."],"exampleFix":"// before\nPulsarAdmin admin = PulsarAdmin.builder().serviceHttpUrl(\"https://broker:8443\")\n    .tlsKeyFilePath(\"/missing/key.pem\")\n    .tlsCertificateFilePath(\"/missing/cert.pem\")\n    .build(); // RuntimeException: Failed to resolve the admin client TLS factory\n// after\nPulsarAdmin admin = PulsarAdmin.builder().serviceHttpUrl(\"https://broker:8443\")\n    .tlsKeyFilePath(\"/etc/pulsar/admin.key.pem\")\n    .tlsCertificateFilePath(\"/etc/pulsar/admin.cert.pem\")\n    .tlsTrustCertsFilePath(\"/etc/pulsar/ca.cert.pem\")\n    .build();","handlingStrategy":"validation","validationCode":"for (String f : new String[]{tlsKeyFile, tlsCertFile, tlsTrustFile}) {\n    if (f != null && !Files.isReadable(Paths.get(f)))\n        throw new IllegalStateException(\"TLS file not readable: \" + f);\n}","typeGuard":null,"tryCatchPattern":"try {\n    PulsarAdmin admin = builder.build();\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"Failed to resolve the admin client TLS factory\")) {\n        log.error(\"TLS setup failed: {}\", e.getCause(), e);\n    }\n    throw e;\n}","preventionTips":["Check all TLS file paths (key, cert, trust) exist and are readable at startup","Provide keystore passwords when files are encrypted","Only enable tlsAuthenticationEnabled when key+cert are configured","Validate PEM files with openssl before deploying"],"tags":["tls","configuration","certificate"],"backgroundTag":"tls-certificate-error","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}