apache/pulsar · error · IllegalArgumentException

certStream provider or stream must not be null

Error message

certStream provider or stream must not be null

What it means

The stream-based AuthenticationDataTls constructor throws IllegalArgumentException when certStreamProvider is null or its Supplier<ByteArrayInputStream>.get() returns null. This variant loads the client certificate chain from a supplied stream instead of a file, so a provider that yields no stream cannot produce usable TLS auth data.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/AuthenticationDataTls.java:73

        if (keyFilePath == null) {
            throw new IllegalArgumentException("keyFilePath must not be null");
        }
        this.certFile = new FileModifiedTimeUpdater(certFilePath);
        this.keyFile = new FileModifiedTimeUpdater(keyFilePath);
        this.tlsCertificates = PemReader.loadCertificatesFromPemFile(certFilePath);
        this.tlsPrivateKey = PemReader.loadPrivateKeyFromPemFile(keyFilePath);
    }

    public AuthenticationDataTls(Supplier<ByteArrayInputStream> certStreamProvider,
            Supplier<ByteArrayInputStream> keyStreamProvider) throws KeyManagementException {
        this(certStreamProvider, keyStreamProvider, null);
    }

    public AuthenticationDataTls(Supplier<ByteArrayInputStream> certStreamProvider,
            Supplier<ByteArrayInputStream> keyStreamProvider, Supplier<ByteArrayInputStream> trustStoreStreamProvider)
            throws KeyManagementException {
        if (certStreamProvider == null || certStreamProvider.get() == null) {
            throw new IllegalArgumentException("certStream provider or stream must not be null");
        }
        if (keyStreamProvider == null || keyStreamProvider.get() == null) {
            throw new IllegalArgumentException("keyStream provider or stream must not be null");
        }
        this.certStreamProvider = certStreamProvider;
        this.keyStreamProvider = keyStreamProvider;
        this.trustStoreStreamProvider = trustStoreStreamProvider;
        this.certStream = certStreamProvider.get();
        this.keyStream = keyStreamProvider.get();
        this.tlsCertificates = PemReader.loadCertificatesFromPemStream(certStream);
        this.tlsPrivateKey = PemReader.loadPrivateKeyFromPemStream(keyStream);
    }
    /*
     * TLS
     */

    @Override
    public boolean hasDataForTls() {

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure certStreamProvider is non-null and returns a valid ByteArrayInputStream containing the PEM certificate chain.
  2. Check that the underlying resource/file the supplier reads actually exists and is readable.
  3. Guard the supplier result before constructing: resolve the stream once and assert it is non-null.

Example fix

// before
Supplier<ByteArrayInputStream> cert = () -> null; // or missing resource
new AuthenticationDataTls(cert, key, trust);
// after
byte[] pem = readClasspathResource("/certs/client-cert.pem"); // throws if absent
new AuthenticationDataTls(() -> new ByteArrayInputStream(pem), key, trust);
Defensive patterns

Strategy: validation

Validate before calling

ByteArrayInputStream cert = certStreamProvider != null ? certStreamProvider.get() : null;
if (cert == null || cert.available() == 0) {
    throw new IllegalStateException("cert stream provider must yield a non-empty PEM stream");
}

Type guard

boolean hasStream(Supplier<ByteArrayInputStream> s) { return s != null && s.get() != null; }

Try / catch

try {
    authData = new AuthenticationDataTls(certStreamProvider, keyStreamProvider, trustStoreStreamProvider);
} catch (IllegalArgumentException | KeyManagementException e) {
    log.error("TLS stream auth misconfigured: {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: Calling new AuthenticationDataTls(certStreamProvider, keyStreamProvider, trustStoreStreamProvider) with certStreamProvider == null, or with a supplier that returns null (e.g. lazy supplier that fails to locate a classpath resource).

Common situations: getResourceAsStream(...) returning null for a missing PEM resource; memoized suppliers that cache null after a failed load; refactored code passing optional suppliers that are empty; in-memory cert provisioning code that silently skips the cert.

Related errors


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