apache/pulsar · error · UnsupportedOperationException
getPublicKey called on a consumer-side CryptoKeyReaderAdapte
Error message
getPublicKey called on a consumer-side CryptoKeyReaderAdapter
What it means
CryptoKeyReaderAdapter wraps a v5 key provider for the legacy CryptoKeyReader interface. An adapter built only with a publicKeyProvider is producer-side; calling getPublicKey on a consumer-side adapter (built with only a privateKeyProvider) throws UnsupportedOperationException because there is no public key provider to delegate to.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/CryptoKeyReaderAdapter.java:67
/**
* Producer-side adapter: only {@link CryptoKeyReader#getPublicKey} is supported.
*/
static CryptoKeyReader forProducer(PublicKeyProvider provider) {
return new CryptoKeyReaderAdapter(provider, null);
}
/**
* Consumer-side adapter: only {@link CryptoKeyReader#getPrivateKey} is supported.
*/
static CryptoKeyReader forConsumer(PrivateKeyProvider provider) {
return new CryptoKeyReaderAdapter(null, provider);
}
@Override
public EncryptionKeyInfo getPublicKey(String keyName, Map<String, String> metadata) {
if (publicKeyProvider == null) {
throw new UnsupportedOperationException(
"getPublicKey called on a consumer-side CryptoKeyReaderAdapter");
}
var v5Key = publicKeyProvider.getPublicKey(keyName).join();
return new EncryptionKeyInfo(v5Key.key(), v5Key.metadata());
}
@Override
public EncryptionKeyInfo getPrivateKey(String keyName, Map<String, String> metadata) {
if (privateKeyProvider == null) {
throw new UnsupportedOperationException(
"getPrivateKey called on a producer-side CryptoKeyReaderAdapter");
}
var v5Key = privateKeyProvider.getPrivateKey(keyName, metadata).join();
return new EncryptionKeyInfo(v5Key.key(), v5Key.metadata());
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Build the adapter with the producer-side factory / a non-null publicKeyProvider before using it for message encryption.
- Use separate adapter instances for producer (public keys) and consumer (private keys).
- Check the factory method used — forConsumer vs forProducer — matches the client role.
Example fix
// before CryptoKeyReader reader = CryptoKeyReaderAdapter.forConsumer(privateKeyProvider); Producer<byte[]> p = client.newProducer().cryptoKeyReader(reader); // producer needs public keys // after CryptoKeyReader reader = CryptoKeyReaderAdapter.forProducer(publicKeyProvider); Producer<byte[]> p = client.newProducer().cryptoKeyReader(reader);
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the adapter was built for producers before wiring it into a Producer CryptoKeyReaderAdapter adapter = CryptoKeyReaderAdapter.forProducer(publicKeyProvider); producerBuilder.cryptoKeyReader(adapter);
Type guard
static boolean supportsPublicKeys(CryptoKeyReaderAdapter a) {
return a != null && a.isProducerSide(); // or track the factory used at construction
} Try / catch
try {
EncryptionKeyInfo ki = adapter.getPublicKey(keyName, metadata);
} catch (UnsupportedOperationException e) {
throw new IllegalStateException("Producer configured with consumer-side key reader", e);
} Prevention
- Always use the role-specific factory (forProducer / forConsumer).
- Never share one CryptoKeyReaderAdapter between producer and consumer.
- Add a startup assertion that producer crypto config includes a public key provider.
When it happens
Trigger: Configuring a producer's encryption with an adapter created from a consumer-side key provider (privateKeyProvider == null), then the producer (or client code) invokes getPublicKey.
Common situations: Copy-pasting consumer crypto configuration into a producer; sharing one adapter instance between a producer and consumer; a library defaulting to the consumer-side factory method CryptoKeyReaderAdapter.forConsumer(...) in producer setup.
Related errors
- getPrivateKey called on a producer-side CryptoKeyReaderAdapt
- privateKeyProvider must be set when failureAction is FAIL
- ${logCtx}Failed to load public key ${keyName}. ${e.getMessag
- ${logCtx}Unsupported key type ${pubKey.getAlgorithm()} for k
- Must provide encryption key name for crypto key reader
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/e1566d66e79912ec.
Report an issue: GitHub.