apache/pulsar · error · java.lang.IllegalArgumentException
tlsPolicy purpose and policy must not be null
Error message
tlsPolicy purpose and policy must not be null
What it means
tlsPolicy(purpose, policy) validates its arguments and throws IllegalArgumentException when either the TlsPurpose or the TlsPolicy is null. The overload tlsPolicy(TlsPolicy) forwards TlsPurpose.CLIENT_DEFAULT, so this error from that path means the policy itself was null. It is a fail-fast guard instead of a NullPointerException deep inside map handling.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/PulsarClientBuilderV5.java:402
return this;
}
@Override
public PulsarClientBuilder transactionPolicy(TransactionPolicy policy) {
conf.setEnableTransaction(true);
this.transactionTimeout = policy.timeout();
return this;
}
@Override
public PulsarClientBuilder tlsPolicy(TlsPolicy policy) {
return tlsPolicy(TlsPurpose.CLIENT_DEFAULT, policy);
}
@Override
public PulsarClientBuilder tlsPolicy(TlsPurpose purpose, TlsPolicy policy) {
if (purpose == null || policy == null) {
throw new IllegalArgumentException("tlsPolicy purpose and policy must not be null");
}
// useTls governs the BINARY BROKER TRANSPORT only, so a policy for a different trust domain must not
// turn it on. Configuring CLIENT_OAUTH2 (the identity provider) against a plaintext pulsar:// broker
// is a legitimate combination — it was enabling TLS toward the broker and failing the connection.
// The policy map itself is what triggers TLS-factory creation, so a non-transport purpose still gets
// its factory without touching the transport.
//
// CLIENT_DEFAULT alone, not every client-role purpose: pip-478.md calls this "one narrow addition",
// being the only v5 expression of the legacy client.conf useTls=true with a plain pulsar:// URL.
// BROKER_CLIENT and plugin-minted purposes (TlsPurpose.client("...")) are client-role too, and
// enabling the transport for them is the same defect this guard was added to fix.
if (TlsPurpose.CLIENT_DEFAULT.equals(purpose)) {
conf.setUseTls(true);
}
Map<TlsPurpose, TlsPolicy> map = conf.getTlsPolicyMap();
if (map == null) {
map = new LinkedHashMap<>();
conf.setTlsPolicyMap(map);View on GitHub (pinned to 820761864e)
Solutions
- Pass a real TlsPolicy built via TlsPolicy.builder()...build().
- Check the source variable for null before calling tlsPolicy and skip or default the TLS configuration when absent.
- If only the purpose may vary, ensure you pass a valid TlsPurpose constant (e.g. TlsPurpose.CLIENT_DEFAULT) or a purpose from TlsPurpose.client(name).
Example fix
// before
TlsPolicy policy = loadFromConfig(); // may be null
builder.tlsPolicy(TlsPurpose.CLIENT_DEFAULT, policy); // IllegalArgumentException if null
// after
TlsPolicy policy = loadFromConfig();
if (policy != null) {
builder.tlsPolicy(TlsPurpose.CLIENT_DEFAULT, policy);
} Defensive patterns
Strategy: validation
Validate before calling
if (purpose != null && policy != null) {
builder.tlsPolicy(purpose, policy);
} Type guard
static boolean isConfigurableTls(TlsPurpose p, TlsPolicy t) { return p != null && t != null; } Prevention
- Build TlsPolicy through TlsPolicy.builder()...build() which itself fails fast on invalid combos.
- Never return null from a config-loading helper for TLS; return Optional<TlsPolicy> and skip configuration when empty.
- Use the enum constants directly (TlsPurpose.CLIENT_DEFAULT) instead of nullable lookups.
When it happens
Trigger: Calling clientBuilder.tlsPolicy(null) or clientBuilder.tlsPolicy(purpose, null), or tlsPolicy(somePurpose, policy) where somePurpose is null; typically the result of a variable that failed to initialize or a configuration lookup that returned null.
Common situations: Loading TlsPolicy from config/properties where a missing key yields null; a factory method returning null on invalid input; refactoring code where the purpose enum constant was removed or renamed.
Related errors
- tlsFactory must not be null
- Positions must not be null
- The replication cluster does not provide TLS encrypted servi
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/1ee3fb7488c895eb.
Report an issue: GitHub.