apache/pulsar · error · IllegalArgumentException
CryptoKeyReader class name required
Error message
CryptoKeyReader class name required
What it means
If an InputSpec for a topic carries a CryptoConfig (input decryption), the cryptoKeyReaderClassName must be a non-blank string naming a class that implements CryptoKeyReader. A blank/null name means Pulsar could not decrypt messages, so doCommonChecks throws IllegalArgumentException('CryptoKeyReader class name required').
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:924
if (filename.contains("..")) {
throw new IllegalArgumentException("Invalid filename: " + filename);
}
if (!new File(filename).exists()) {
throw new IllegalArgumentException("The supplied go file does not exist");
}
}
if (functionConfig.getInputSpecs() != null) {
functionConfig.getInputSpecs().forEach((topicName, conf) -> {
// receiver queue size should be >= 0
if (conf.getReceiverQueueSize() != null && conf.getReceiverQueueSize() < 0) {
throw new IllegalArgumentException(
"Receiver queue size should be >= zero");
}
if (conf.getCryptoConfig() != null && isBlank(conf.getCryptoConfig().getCryptoKeyReaderClassName())) {
throw new IllegalArgumentException(
"CryptoKeyReader class name required");
}
if (conf.getMessagePayloadProcessorConfig() != null && isBlank(
conf.getMessagePayloadProcessorConfig().getClassName())) {
throw new IllegalArgumentException(
"MessagePayloadProcessor class name required");
}
});
}
if (functionConfig.getProducerConfig() != null
&& functionConfig.getProducerConfig().getCryptoConfig() != null) {
if (isBlank(functionConfig.getProducerConfig().getCryptoConfig().getCryptoKeyReaderClassName())) {
throw new IllegalArgumentException("CryptoKeyReader class name required");
}
if (functionConfig.getProducerConfig().getCryptoConfig().getEncryptionKeys() == null
|| functionConfig.getProducerConfig().getCryptoConfig().getEncryptionKeys().length == 0) {View on GitHub (pinned to 820761864e)
Solutions
- Set the fully qualified class name of your CryptoKeyReader implementation: cryptoConfig.setCryptoKeyReaderClassName("com.example.MyKeyReader")
- Ensure the implementation class is available on the function worker/instance classpath (nar/jar shipping)
- If input decryption is not needed, remove the CryptoConfig from the InputSpec entirely
- Check that the property/env substitution feeding the class name actually resolves to a non-blank value
Example fix
// before
CryptoConfig crypto = new CryptoConfig(); // className blank
inputSpec.setCryptoConfig(crypto);
// after
CryptoConfig crypto = new CryptoConfig();
crypto.setCryptoKeyReaderClassName("com.example.MyCryptoKeyReader");
inputSpec.setCryptoConfig(crypto); Defensive patterns
Strategy: validation
Validate before calling
if (spec.getCryptoConfig() != null
&& (spec.getCryptoConfig().getCryptoKeyReaderClassName() == null
|| spec.getCryptoConfig().getCryptoKeyReaderClassName().isBlank())) {
throw new IllegalStateException("cryptoKeyReaderClassName required for input topic " + topic);
} Type guard
boolean hasCryptoKeyReader(org.apache.pulsar.functions.proto.Function.CryptoConfig c) {
return c == null || (c.getCryptoKeyReaderClassName() != null
&& !c.getCryptoKeyReaderClassName().isBlank());
} Try / catch
try {
admin.functions().createFunction(conf);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("CryptoKeyReader class name")) {
conf.getInputSpecs().values().forEach(s -> {
if (s.getCryptoConfig() != null && s.getCryptoConfig().getCryptoKeyReaderClassName().isBlank()) {
s.getCryptoConfig().setCryptoKeyReaderClassName(DEFAULT_KEY_READER_CLASS);
}
});
admin.functions().createFunction(conf);
} else throw e;
} Prevention
- Always pair CryptoConfig with a concrete CryptoKeyReader class on the function classpath
- Resolve env/property placeholders in class names before submission and fail on unresolved values
- Only attach CryptoConfig to inputs that are actually encrypted
When it happens
Trigger: Setting InputSpec.setCryptoConfig(new CryptoConfig()) (or with setCryptoKeyReaderClassName("")/whitespace) on any function input topic, then calling createFunction/updateFunction.
Common situations: Enabling input decryption but forgetting to point at the key reader implementation; crypto config copied from producer config where the key was set elsewhere; blank string produced by environment-variable substitution that failed; class name left as template placeholder.
Related errors
- Must provide encryption key name for crypto key reader
- Missing encryption key name for producer crypto key reader
- Unable to initialize crypto config %s
- When effectively once processing guarantee is specified, ret
- Only one of retain ordering or retain key ordering can be se
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/f4fe3d13bd5a5dc6.
Report an issue: GitHub.