apache/pulsar · error · RuntimeException

Failed to obtain broker-client authentication TLS material

Error message

Failed to obtain broker-client authentication TLS material

What it means

FileBasedTlsFactory.authMaterialSupplier returns a Supplier of AuthenticationDataProvider for broker-client TLS. Any PulsarClientException thrown while resolving the client authentication data (e.g. via getAuthData) is rethrown as a RuntimeException with this message, preserving the original as the cause.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/tls/impl/FileBasedTlsFactory.java:155

        this.registry = Map.copyOf(built);
    }

    /**
     * Adapt a component's broker-client {@link Authentication} to a per-refresh
     * {@link AuthenticationDataProvider} supplier for use with the {@code BROKER_CLIENT} fold constructor.
     * The supplier re-reads {@code getAuthData()} on each poll so credential rotation is observed; a checked
     * {@link PulsarClientException} is rethrown unchecked and handled by the factory's keep-last-good poll.
     *
     * @param authentication the broker-client authentication plugin (never {@code null})
     * @return a supplier of the plugin's current authentication data
     */
    public static Supplier<AuthenticationDataProvider> authMaterialSupplier(Authentication authentication) {
        Objects.requireNonNull(authentication, "authentication must not be null");
        return () -> {
            try {
                return resolveAuthData(authentication);
            } catch (PulsarClientException e) {
                throw new RuntimeException("Failed to obtain broker-client authentication TLS material", e);
            }
        };
    }

    // The BROKER_CLIENT TLS fold is host-agnostic — TLS key material does not vary by peer — so the
    // host-less getAuthData() is exactly what we want; isolate its deprecation here.
    @SuppressWarnings("deprecation")
    private static AuthenticationDataProvider resolveAuthData(Authentication authentication)
            throws PulsarClientException {
        return authentication.getAuthData();
    }

    @Override
    public CompletableFuture<Void> initialize(TlsFactoryInitContext context) {
        try {
            Objects.requireNonNull(context, "context must not be null");
            // Required, not optional: every acquisition path in this factory reads files and parses key
            // material. Without an executor the work would run inline on the caller's thread, which the SPI

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the chained cause (e.getCause(), a PulsarClientException) for the actual failure
  2. Verify all cert/key/credential files referenced by the Authentication config exist and are readable
  3. Ensure the Authentication object was fully initialized before the supplier is invoked
  4. Fix the underlying PulsarClientException condition rather than catching the wrapper

Example fix

// before
AuthenticationTls auth = new AuthenticationTls(); // cert paths unset
FileBasedTlsFactory.authMaterialSupplier(auth).get(); // throws RuntimeException
// after
AuthenticationTls auth = new AuthenticationTls();
auth.configure(Map.of("tlsCertFile", "/etc/pulsar/cert.pem", "tlsKeyFile", "/etc/pulsar/key.pem"));
FileBasedTlsFactory.authMaterialSupplier(auth).get();
Defensive patterns

Strategy: try-catch

Validate before calling

// before invoking the supplier, check configured material paths exist:
for (String p : List.of(certPath, keyPath)) {
    if (p != null && !Files.isReadable(Path.of(p))) throw new IllegalStateException("Missing auth material: " + p);
}

Try / catch

try {
    AuthenticationDataProvider data = authMaterialSupplier(authentication).get();
} catch (RuntimeException e) {
    Throwable cause = e.getCause(); // PulsarClientException with the real reason
    log.error("Broker-client TLS auth material unavailable: {}", cause == null ? e : cause, cause);
}

Prevention

When it happens

Trigger: Invoking the supplier returned by authMaterialSupplier(authentication) when the configured Authentication implementation's getAuthData() throws PulsarClientException, e.g. because referenced certificate/key/credential files are missing or unreadable.

Common situations: Broker-client auth config pointing to cert/key paths that do not exist or are unreadable by the process user; Authentication provider not initialized before the supplier is used; invalid auth state after config reload.

Understand the failure class

Related errors


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