apache/pulsar · error · PulsarClientException.CryptoException

Keyname or KeyReader is null

Error message

Keyname or KeyReader is null

What it means

MessageCryptoBc.addPublicKeyCipher validates its arguments before doing any crypto work: if either the key name or the CryptoKeyReader is null it cannot obtain the encryption key, so it throws PulsarClientException.CryptoException immediately. This is a fail-fast argument check, not a crypto failure.

Source

Thrown at pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java:373

     *
     * @param keyNames List of public keys to encrypt data key
     *
     * @param keyReader Implementation to read the key values
     *
     */
    @Override
    public void addPublicKeyCipher(Set<String> keyNames, CryptoKeyReader keyReader) throws CryptoException {
        // Rotate the encryption key each time this method is called
        encryptionKey = generateEncryptionKey();

        for (String key : keyNames) {
            addPublicKeyCipher(key, keyReader);
        }
    }

    private void addPublicKeyCipher(String keyName, CryptoKeyReader keyReader) throws CryptoException {
        if (keyName == null || keyReader == null) {
            throw new PulsarClientException.CryptoException("Keyname or KeyReader is null");
        }

        // Read the public key and its info using callback
        EncryptionKeyInfo keyInfo = keyReader.getPublicKey(keyName, null);

        PublicKey pubKey;

        try {
            pubKey = loadPublicKey(keyInfo.getKey());
        } catch (Exception e) {
            String msg = logCtx + "Failed to load public key " + keyName + ". " + e.getMessage();
            log.error(msg);
            throw new PulsarClientException.CryptoException(msg);
        }

        Cipher dataKeyCipher;
        byte[] encryptedKey;
        try {

View on GitHub (pinned to 820761864e)

Solutions

  1. Configure a CryptoKeyReader on the builder: .addKeyReader(new DefaultCryptoKeyReader(keyReaderFilePath))
  2. Pass a non-null key name to addEncryptionKey() and verify it matches a key your reader can serve via getPublicKey
  3. Validate configuration loading so keyName/keyReaderPath values are actually populated before building the producer
  4. Null-check these values in your own startup code to fail with a clearer message

Example fix

// before
Producer<byte[]> p = client.newProducer().addEncryptionKey("myapp.key").create(); // no key reader
// after
CryptoKeyReader reader = new DefaultCryptoKeyReader("/path/to/public/key.pem");
Producer<byte[]> p = client.newProducer().addKeyReader(reader).addEncryptionKey("myapp.key").create();
Defensive patterns

Strategy: validation

Validate before calling

if (keyName == null || keyName.isEmpty()) {
    throw new IllegalArgumentException("encryption key name must be set");
}
if (keyReader == null) {
    throw new IllegalArgumentException("CryptoKeyReader must be configured before enabling encryption");
}

Try / catch

try {
    producer = client.newProducer().addKeyReader(keyReader).addEncryptionKey(keyName).create();
} catch (PulsarClientException.CryptoException e) {
    log.error("Encryption config incomplete: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling producer/reader addEncryptionKey(keyName) (which delegates to addPublicKeyCipher) with a null keyName, or when no CryptoKeyReader has been configured on the client builder so keyReader is null.

Common situations: Forgetting to call .addKeyReader(keyReader) (or the older cryptoKeyReader config) on the ProducerBuilder while enabling end-to-end encryption; a typo in the key name variable that leaves it uninitialized; building configuration programmatically where a required property failed to load and stayed null.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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