{"record":{"id":"a7739d8196fdaa5f","repo":"apache/pulsar","slug":"no-tls-material-configured-for-server-purpose-purp","errorCode":null,"errorMessage":"No TLS material configured for server purpose purpose","messagePattern":"No TLS material configured for server purpose purpose","errorType":"exception","errorClass":"TlsMaterialUnavailableException","httpStatus":null,"severity":"critical","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/tls/impl/FileBasedTlsFactory.java","lineNumber":420,"sourceCode":"        }\n    }\n\n    /**\n     * Resolve a requested purpose to the {@link RegisteredSource} that owns its material, applying the\n     * role's terminal-resolution rule when nothing is configured for the purpose.\n     *\n     * @throws TlsMaterialUnavailableException when a server-role purpose has no material configured\n     */\n    private RegisteredSource resolve(TlsPurpose purpose) {\n        Objects.requireNonNull(purpose, \"purpose must not be null\");\n        RegisteredSource source = registry.get(purpose);\n        if (source != null) {\n            return source;\n        }\n        if (purpose.role() == TlsPurpose.Role.CLIENT) {\n            return systemDefaultSource();\n        }\n        throw new TlsMaterialUnavailableException(\n                \"No TLS material configured for server purpose \" + purpose);\n    }\n\n    private RegisteredSource systemDefaultSource() {\n        RegisteredSource existing = this.systemDefaultSource;\n        if (existing != null) {\n            return existing;\n        }\n        synchronized (this) {\n            if (this.systemDefaultSource == null) {\n                // System default: verify hostnames, OS trust store, no client certificate. A constant\n                // source (no files, never rotates).\n                TlsPolicy defaultPolicy = TlsPolicy.builder().build();\n                this.systemDefaultSource = new RegisteredSource(\n                        TlsPurpose.CLIENT_DEFAULT, defaultPolicy, null);\n            }\n            return this.systemDefaultSource;\n        }","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/tls/impl/FileBasedTlsFactory.java#L402-L438","documentation":"The TLS factory resolves a material source for a TlsPurpose. If no registered source applies and the purpose role is SERVER (clients fall back to systemDefaultSource), no server-side certificate identity is configured, so TlsMaterialUnavailableException is thrown — the server could not present any TLS identity.","triggerScenarios":"Building a server-role TLS instance via createInstance/createOneShot while TlsPolicy has neither keyStorePath nor certificateFilePath/keyFilePath set, and no other registered material source matches the purpose.","commonSituations":"Broker/proxy TLS listeners enabled (tlsEnabled=true) without a server keystore or PEM pair configured; a policy copy that dropped server settings; using a server-role purpose with a client-only policy.","solutions":["Configure server identity: set keyStorePath (with password) or certificateFilePath + keyFilePath in TlsPolicy","Ensure the policy object wired into the factory is the one holding the server TLS settings","Use a client-role TlsPurpose if this path should fall back to system defaults","Register a custom material source for the purpose if provisioning programmatically"],"exampleFix":"// before\nTlsPolicy policy = TlsPolicy.builder().tlsEnabled(true).build(); // no server identity\n// after\nTlsPolicy policy = TlsPolicy.builder()\n    .tlsEnabled(true)\n    .keyStorePath(\"/etc/pulsar/broker.keystore.jks\")\n    .keyStorePassword(\"********\")\n    .build();","handlingStrategy":"validation","validationCode":"boolean hasServerIdentity(TlsPolicy p) {\n    return p.keyStorePath() != null || (p.certificateFilePath() != null && p.keyFilePath() != null);\n}\n// check before constructing a server-role TlsPurpose","typeGuard":null,"tryCatchPattern":"try {\n    factory.createInstance(serverPurpose, SslContext.class).join();\n} catch (TlsMaterialUnavailableException e) {\n    log.error(\"Server TLS identity not configured: {}\", e.getMessage());\n}","preventionTips":["Never enable TLS listeners without keystore or PEM identity configured","Wire the TlsPolicy object that actually holds server settings into the factory","Add a startup config check for every server-role purpose"],"tags":["tls","server","missing-configuration"],"backgroundTag":"missing-tls-certificate","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"}