apache/pulsar · error · UnsupportedOperationException
getPrivateKey called on a producer-side CryptoKeyReaderAdapt
Error message
getPrivateKey called on a producer-side CryptoKeyReaderAdapter
What it means
This is the mirror of the producer-side case: CryptoKeyReaderAdapter built only with a privateKeyProvider is consumer-side. Calling getPrivateKey (needed for decryption on the consumer) on a producer-side adapter (privateKeyProvider == null) throws UnsupportedOperationException.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/CryptoKeyReaderAdapter.java:77
*/
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 a non-null privateKeyProvider (consumer-side factory) for consumer decryption.
- Give the consumer its own adapter instance with the private key provider.
- Verify environment/keystore actually exposes the private keys the consumer needs.
Example fix
// before CryptoKeyReader reader = CryptoKeyReaderAdapter.forProducer(publicKeyProvider); Consumer<byte[]> c = client.newConsumer().cryptoKeyReader(reader); // consumer needs private keys // after CryptoKeyReader reader = CryptoKeyReaderAdapter.forConsumer(privateKeyProvider); Consumer<byte[]> c = client.newConsumer().cryptoKeyReader(reader);
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the adapter was built for consumers before wiring it into a Consumer CryptoKeyReaderAdapter adapter = CryptoKeyReaderAdapter.forConsumer(privateKeyProvider); consumerBuilder.cryptoKeyReader(adapter);
Type guard
static boolean supportsPrivateKeys(CryptoKeyReaderAdapter a) {
return a != null && a.isConsumerSide(); // or track the factory used at construction
} Try / catch
try {
EncryptionKeyInfo ki = adapter.getPrivateKey(keyName, metadata);
} catch (UnsupportedOperationException e) {
throw new IllegalStateException("Consumer configured with producer-side key reader", e);
} Prevention
- Give each client role its own adapter instance.
- Verify private keys are available in the environment/keystore for consumers.
- Document which factory method maps to which client role in team conventions.
When it happens
Trigger: Configuring a consumer's decryption with an adapter created from a producer-side key provider (publicKeyProvider only), then the consumer invokes getPrivateKey during message decryption.
Common situations: Reusing the producer's CryptoKeyReader for a consumer; defaulting configuration code to the producer factory; one adapter shared across a client used for both producing and consuming.
Related errors
- getPublicKey called on a consumer-side CryptoKeyReaderAdapte
- 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/1347704ebce2d3a5.
Report an issue: GitHub.