apache/pulsar · error · IllegalStateException
Client TLS factory <factory.getClass().getName()> supplied n
Error message
Client TLS factory <factory.getClass().getName()> supplied no Netty SslContext for purpose <purpose>
What it means
probe() validates a PulsarTlsFactory by asking it to produce a Netty SslContext for a given TlsPurpose (client/server connection) via TlsContextAcquisition. If the future completes with an empty Optional, the factory failed to supply a context for that purpose, and an IllegalStateException is thrown naming the factory class and purpose. This signals the factory implementation does not support or did not configure that purpose.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/ClientTlsFactorySupport.java:620
.build();
}
/**
* Fail-fast probe: build one instance of the purpose and dispose it, surfacing a configuration error
* (e.g. a missing cert file) as an actionable {@link IllegalArgumentException}. Acquisition goes through
* {@link TlsContextAcquisition}, so a custom factory that supplies only the JDK {@code SSLContext}
* fallback probes successfully via the framework-synthesized Netty context.
*
* @param factory the initialized factory
* @param purpose the purpose to probe
* @param synthesis the settings baked into a synthesized Netty context on the fallback path
*/
public static void probe(PulsarTlsFactory factory, TlsPurpose purpose, TlsSynthesisSpec synthesis) {
try {
Optional<TlsHandle<SslContext>> handle =
TlsContextAcquisition.acquireNettyContext(factory, purpose, synthesis).get();
if (handle.isEmpty()) {
throw new IllegalStateException("Client TLS factory " + factory.getClass().getName()
+ " supplied no Netty SslContext for purpose " + purpose);
}
handle.get().dispose();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("Interrupted while probing the client TLS factory", e);
} catch (ExecutionException | CompletionException e) {
Throwable cause = e.getCause() != null ? e.getCause() : e;
throw new IllegalArgumentException("Client TLS configuration is invalid for purpose " + purpose
+ ": " + cause.getMessage(), cause);
}
}
private static void initializeBlocking(PulsarTlsFactory factory, TlsFactoryInitContext context)
throws Exception {
try {
factory.initialize(context).get();
} catch (ExecutionException e) {View on GitHub (pinned to 820761864e)
Solutions
- Implement the missing purpose in your PulsarTlsFactory so acquireNettyContext returns a valid SslContext handle.
- Supply the required key/cert/truststore config so the factory can synthesize the context.
- Check TlsContextAcquisition logs for why the acquisition completed empty (async failure swallowed).
- Update the custom factory for the current Pulsar TlsPurpose enum / synthesis spec API.
Example fix
// before (custom factory) Optional<TlsHandle<SslContext>> h = purpose == TlsPurpose.CLIENT ? build() : Optional.empty(); // after Optional<TlsHandle<SslContext>> h = buildFor(purpose, synthesis); // build for every purpose
Defensive patterns
Strategy: validation
Validate before calling
boolean supportsPurpose(PulsarTlsFactory f, TlsPurpose p) {
try {
var h = TlsContextAcquisition.acquireNettyContext(f, p, spec).get(5, TimeUnit.SECONDS);
boolean ok = h.isPresent(); h.ifPresent(TlsHandle::dispose);
return ok;
} catch (Exception e) { return false; }
} Try / catch
try {
ClientTlsFactorySupport.probe(factory, purpose, spec);
} catch (IllegalStateException e) {
if (e.getMessage().contains("supplied no Netty SslContext")) {
log.error("Factory lacks support/keys for purpose " + purpose, e);
}
} Prevention
- Implement all TlsPurpose cases in custom factories
- Load key/cert material before registration so context creation cannot be skipped
- Add a startup smoke test that probes each purpose
- Log inside acquireNettyContext to surface swallowed async failures
When it happens
Trigger: resolveClientTlsFactory probing a custom PulsarTlsFactory whose acquireNettyContext returns empty for a purpose (e.g. factory only implements client auth context but probe requests server-purpose synthesis, or keys/certs missing so the factory yields no context).
Common situations: Custom TLS factory that returns Optional.empty for unsupported purposes; missing key/cert material so context creation is skipped; purpose/purpose-specific synthesis spec mismatch after a Pulsar upgrade adding new purposes.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- No TLS context available (factory not initialized or closed)
- The replication cluster does not provide TLS encrypted servi
- No ${scheme} URL configured for broker ${brokerId}
- Issuer URL does not use https, but must:
- Failed to get TLS certificates from client
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b1dbc223abd7add2.
Report an issue: GitHub.