apache/pulsar · error · IllegalArgumentException
The crypto key reader class %s does not implement the desire
Error message
The crypto key reader class %s does not implement the desired constructor.
What it means
Function crypto key readers must expose a constructor taking a single Map (the config map). After class/interface checks pass, validateCryptoKeyReader inspects declared constructors via ByteBuddy and throws this IllegalArgumentException if no Map-arg constructor exists.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java:93
String cryptoClassName = conf.getCryptoKeyReaderClassName();
TypeDescription cryptoClass = null;
try {
cryptoClass = typePool.describe(cryptoClassName).resolve();
} catch (TypePool.Resolution.NoSuchTypeException e) {
throw new IllegalArgumentException(
String.format("The crypto key reader class %s does not exist", cryptoClassName));
}
if (!cryptoClass.asErasure().isAssignableTo(CryptoKeyReader.class)) {
throw new IllegalArgumentException(
String.format("%s does not implement %s", cryptoClassName, CryptoKeyReader.class.getName()));
}
boolean hasConstructor = cryptoClass.getDeclaredMethods().stream()
.anyMatch(method -> method.isConstructor() && method.getParameters().size() == 1
&& method.getParameters().get(0).getType().asErasure().represents(Map.class));
if (!hasConstructor) {
throw new IllegalArgumentException(
String.format("The crypto key reader class %s does not implement the desired constructor.",
conf.getCryptoKeyReaderClassName()));
}
if (isProducer && (conf.getEncryptionKeys() == null || conf.getEncryptionKeys().length == 0)) {
throw new IllegalArgumentException("Missing encryption key name for producer crypto key reader");
}
}
public static void validateMessagePayloadProcessor(MessagePayloadProcessorConfig conf, TypePool typePool) {
if (isEmpty(conf.getClassName())) {
return;
}
String payloadProcessorClassName = conf.getClassName();
TypeDescription payloadProcessorClass = null;
try {
payloadProcessorClass = typePool.describe(payloadProcessorClassName).resolve();View on GitHub (pinned to 820761864e)
Solutions
- Add a public constructor accepting a single java.util.Map parameter (often Map<String, Object>)
- Alternatively add a no-arg constructor plus the Map constructor if used in both contexts
- Ensure the constructor is not private and is declared on the class (not only inherited)
Example fix
// before
public class MyKeyReader implements CryptoKeyReader {
public MyKeyReader() { ... }
}
// after
public class MyKeyReader implements CryptoKeyReader {
public MyKeyReader() { this(Collections.emptyMap()); }
public MyKeyReader(Map<String, Object> config) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
boolean hasMapCtor = Arrays.stream(cryptoClass.getConstructors())
.anyMatch(c -> c.getParameterCount() == 1 && Map.class.isAssignableFrom(c.getParameterTypes()[0]));
if (!hasMapCtor) throw new IllegalStateException("Add a Map-arg constructor to " + cryptoClass.getName()); Try / catch
try {
ValidatorUtils.validateCryptoKeyReader(conf, typePool, isProducer);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("desired constructor")) {
// add public MyKeyReader(Map<String, Object> config) { ... }
}
throw e;
} Prevention
- Always provide both a no-arg and a Map-arg constructor in custom key readers
- Keep constructors public and on the class itself
- Document the required constructor in your connector README
When it happens
Trigger: Providing a custom CryptoKeyReader implementation that only has a no-arg constructor or constructors with other signatures, while the function framework needs to instantiate it with a Map config.
Common situations: Writing a CryptoKeyReader the same way as for raw Pulsar clients (no-arg) and reusing it in functions; refactoring removed the Map constructor; constructor made private.
Related errors
- User class doesn't have such method
- Key reader class does not have constructor accepts map
- Message payload processor class does not have default constr
- Message payload processor class does not have constructor ac
- User class must have a no-arg constructor
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/134203e1d903cdc8.
Report an issue: GitHub.