{"record":{"id":"8fec273cb07a8e2b","repo":"apache/pulsar","slug":"key-reader-class-does-not-have-constructor-accepts","errorCode":null,"errorMessage":"Key reader class does not have constructor accepts map","messagePattern":"Key reader class does not have constructor accepts map","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/CryptoUtils.java","lineNumber":105,"sourceCode":"\n        return bldr.build();\n    }\n\n    public static CryptoKeyReader getCryptoKeyReaderInstance(String className, Map<String, Object> configs,\n                                                             ClassLoader classLoader) {\n        Class<?> cryptoClass;\n        try {\n            cryptoClass = ClassLoaderUtils.loadClass(className, classLoader);\n        } catch (ClassNotFoundException e) {\n            throw new RuntimeException(\n                    String.format(\"Failed to load crypto key reader class %sx\", className));\n        }\n\n        try {\n            Constructor<?> ctor = cryptoClass.getConstructor(Map.class);\n            return (CryptoKeyReader) ctor.newInstance(configs);\n        } catch (NoSuchMethodException e) {\n            throw new RuntimeException(\"Key reader class does not have constructor accepts map\", e);\n        } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {\n            throw new RuntimeException(\"Failed to create instance for key reader class\", e);\n        }\n    }\n\n    public static ProducerCryptoFailureAction getProducerCryptoFailureAction(CryptoSpec.FailureAction action) {\n        switch (action) {\n            case FAIL:\n                return ProducerCryptoFailureAction.FAIL;\n            case SEND:\n                return ProducerCryptoFailureAction.SEND;\n            default:\n                throw new RuntimeException(\n                        \"Unknown producer protobuf failure action \" + action.name());\n        }\n    }\n\n    public static ConsumerCryptoFailureAction getConsumerCryptoFailureAction(CryptoSpec.FailureAction action) {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/CryptoUtils.java#L87-L123","documentation":"After the CryptoKeyReader class is loaded, CryptoUtils requires a public constructor accepting a single Map (of configs) to instantiate it. If the class has no Map-argument constructor (NoSuchMethodException), this RuntimeException with cause is thrown. This is an SPI convention: crypto key reader implementations must expose CryptoKeyReader(Map<String,Object> configs).","triggerScenarios":"A custom CryptoKeyReader class exists on the classpath but only defines a no-arg constructor (or default constructor only), while getCryptoKeyReaderInstance calls cryptoClass.getConstructor(Map.class).","commonSituations":"implementations written against older examples using a no-arg constructor; refactoring that removed the Map constructor; implementing CryptoKeyReader in Kotlin/Scala without generating the Map-arg constructor.","solutions":["Add a public constructor taking Map<String,Object> (raw Map parameter per getConstructor(Map.class)) to your CryptoKeyReader implementation","If the class cannot be changed, wrap it in an adapter class with the required Map constructor","Confirm the constructor is public and takes exactly one java.util.Map parameter (not a subtype or Object)"],"exampleFix":"// before\nclass MyKeyReader implements CryptoKeyReader {\n    public MyKeyReader() { }\n    ...\n}\n// after\nclass MyKeyReader implements CryptoKeyReader {\n    public MyKeyReader(Map<String, Object> configs) {\n        // initialize from configs\n    }\n    ...\n}","handlingStrategy":"validation","validationCode":"Class<?> c = ClassLoaderUtils.loadClass(className, classLoader);\nboolean hasMapCtor = false;\nfor (Constructor<?> ctor : c.getConstructors()) {\n    if (ctor.getParameterCount() == 1 && ctor.getParameterTypes()[0] == Map.class) { hasMapCtor = true; }\n}\nif (!hasMapCtor) throw new IllegalStateException(className + \" needs a public Map-arg constructor\");","typeGuard":null,"tryCatchPattern":"try {\n    CryptoKeyReader reader = CryptoUtils.getCryptoKeyReaderInstance(className, configs, classLoader);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"constructor accepts map\")) { /* add CryptoKeyReader(Map) constructor */ }\n}","preventionTips":["Follow the SPI convention: implement a public CryptoKeyReader(Map<String,Object>) constructor","Unit-test instantiation of custom crypto classes via reflection before deploying","Document the required constructor in your client crypto config templates"],"tags":["crypto","reflection","constructor","pulsar-client"],"backgroundTag":"missing-constructor","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}