apache/pulsar · error · RuntimeException
Failed to create instance for key reader class
Error message
Failed to create instance for key reader class
What it means
CryptoUtils.getCryptoKeyReaderInstance reflectively instantiates a user-provided CryptoKeyReader class using its (java.util.Map) constructor. This error means the constructor exists (otherwise a NoSuchMethodException would be thrown) but invoking it failed — either the class is abstract/an interface and cannot be instantiated, the constructor threw an exception, or the class/constructor is not accessible. It wraps the underlying reflective failure in a RuntimeException.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/CryptoUtils.java:107
}
public static CryptoKeyReader getCryptoKeyReaderInstance(String className, Map<String, Object> configs,
ClassLoader classLoader) {
Class<?> cryptoClass;
try {
cryptoClass = ClassLoaderUtils.loadClass(className, classLoader);
} catch (ClassNotFoundException e) {
throw new RuntimeException(
String.format("Failed to load crypto key reader class %sx", className));
}
try {
Constructor<?> ctor = cryptoClass.getConstructor(Map.class);
return (CryptoKeyReader) ctor.newInstance(configs);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Key reader class does not have constructor accepts map", e);
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new RuntimeException("Failed to create instance for key reader class", e);
}
}
public static ProducerCryptoFailureAction getProducerCryptoFailureAction(CryptoSpec.FailureAction action) {
switch (action) {
case FAIL:
return ProducerCryptoFailureAction.FAIL;
case SEND:
return ProducerCryptoFailureAction.SEND;
default:
throw new RuntimeException(
"Unknown producer protobuf failure action " + action.name());
}
}
public static ConsumerCryptoFailureAction getConsumerCryptoFailureAction(CryptoSpec.FailureAction action) {
switch (action) {
case FAIL:View on GitHub (pinned to 820761864e)
Solutions
- Fix the user-supplied CryptoKeyReader implementation: make it a public, concrete (non-abstract) class with a public constructor accepting java.util.Map
- Inspect the wrapped cause (getCause() of this RuntimeException — often InvocationTargetException) and fix whatever made the constructor throw (e.g. missing/invalid entries in the configs map, unreachable key service)
- Ensure the class is on the function worker's classpath and the configured class name matches the deployed artifact version
- Log configs keys and verify required parameters before constructing the reader
Example fix
// before
public class MyKeyReader implements CryptoKeyReader {
MyKeyReader(Map<String, String> configs) { ... } // package-private
}
// after
public class MyKeyReader implements CryptoKeyReader {
public MyKeyReader(Map<String, String> configs) { ... } // public, no-throw setup
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName(className);
if (c.isInterface() || Modifier.isAbstract(c.getModifiers()))
throw new IllegalArgumentException(className + " is not instantiable");
if (!CryptoKeyReader.class.isAssignableFrom(c))
throw new IllegalArgumentException(className + " does not implement CryptoKeyReader");
try {
Constructor<?> ctor = c.getConstructor(Map.class);
if (!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(c.getModifiers()))
throw new IllegalArgumentException(className + " or its Map constructor is not public");
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(className + " lacks a public (Map) constructor");
}
// also pre-check any required keys your reader expects: configs.containsKey("keyPath") Try / catch
try {
CryptoKeyReader reader = CryptoUtils.getCryptoKeyReaderInstance(cls, configs);
} catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause instanceof InvocationTargetException)
log.error("Key reader constructor threw", cause.getCause());
else if (cause instanceof InstantiationException)
log.error("Class is abstract/interface", cause);
else
log.error("Inaccessible class/constructor", cause);
throw new IllegalArgumentException("Invalid CryptoKeyReader class: " + cls.getName(), e);
} Prevention
- Make every CryptoKeyReader implementation public, concrete, with a public Map constructor
- Keep constructor logic minimal; defer I/O (key loading) to the first decrypt call so construction never throws
- Log the constructor's exception chain (cause.getCause() for InvocationTargetException) when diagnosing
- Pin the artifact containing the reader to the version expected on the worker classpath
When it happens
Trigger: Calling getCryptoKeyReaderInstance(class, configs) with: an abstract class or interface implementing CryptoKeyReader (InstantiationException); a constructor that throws on the supplied configs map (InvocationTargetException); a non-public class/constructor without setAccessible (IllegalAccessException).
Common situations: Misconfigured function/crypto config pointing at the wrong class name or a class from an old artifact version; a key reader whose constructor throws because a required key/certificate path in configs is missing or unreadable (KMS/credentials unavailable); a package-private CryptoKeyReader implementation that isn't exported.
Related errors
- Failed to instantiate ${className}
- User class must be concrete
- The ${alg.name()} algorithm does not support Key Pairs.
- Illegal base64 character or Key file ${keyConfUrl} doesn't e
- Exception caused while converting configuration: ${message}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/1490cda2d8b6ac5b.
Report an issue: GitHub.