{"record":{"id":"2aa6e5a524011660","repo":"apache/pulsar","slug":"missing-encryption-key-name-for-producer-crypto-ke","errorCode":null,"errorMessage":"Missing encryption key name for producer crypto key reader","messagePattern":"Missing encryption key name for producer crypto key reader","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java","lineNumber":99,"sourceCode":"                    String.format(\"The crypto key reader class %s does not exist\", cryptoClassName));\n        }\n        if (!cryptoClass.asErasure().isAssignableTo(CryptoKeyReader.class)) {\n            throw new IllegalArgumentException(\n                    String.format(\"%s does not implement %s\", cryptoClassName, CryptoKeyReader.class.getName()));\n        }\n\n        boolean hasConstructor = cryptoClass.getDeclaredMethods().stream()\n                .anyMatch(method -> method.isConstructor() && method.getParameters().size() == 1\n                        && method.getParameters().get(0).getType().asErasure().represents(Map.class));\n\n        if (!hasConstructor) {\n            throw new IllegalArgumentException(\n                    String.format(\"The crypto key reader class %s does not implement the desired constructor.\",\n                            conf.getCryptoKeyReaderClassName()));\n        }\n\n        if (isProducer && (conf.getEncryptionKeys() == null || conf.getEncryptionKeys().length == 0)) {\n            throw new IllegalArgumentException(\"Missing encryption key name for producer crypto key reader\");\n        }\n    }\n\n    public static void validateMessagePayloadProcessor(MessagePayloadProcessorConfig conf, TypePool typePool) {\n        if (isEmpty(conf.getClassName())) {\n            return;\n        }\n\n        String payloadProcessorClassName = conf.getClassName();\n        TypeDescription payloadProcessorClass = null;\n        try {\n            payloadProcessorClass = typePool.describe(payloadProcessorClassName).resolve();\n        } catch (TypePool.Resolution.NoSuchTypeException e) {\n            throw new IllegalArgumentException(\n                    String.format(\"The message payload processor class %s does not exist\", payloadProcessorClassName));\n        }\n        if (!payloadProcessorClass.asErasure().isAssignableTo(MessagePayloadProcessor.class)) {\n            throw new IllegalArgumentException(String.format(\"%s does not implement %s\", payloadProcessorClassName,","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java#L81-L117","documentation":"When a crypto key reader is configured on the producer side (isProducer == true), encryptionKeys must list at least one public key name used to encrypt the message. validateCryptoKeyReader throws this IllegalArgumentException when getEncryptionKeys() is null or empty.","triggerScenarios":"Setting cryptoKeyReaderClassName in a source function's producer conf without setting encryptionKeys, or setting encryptionKeys to an empty array, while isProducer is true.","commonSituations":"Copying a consumer-side crypto config into a source function; forgetting the --encryption-key CLI flag; clearing encryption keys after switching to encrypted topics.","solutions":["Set encryptionKeys in the producer conf (or pass --encryption-key) with the key names available from the key reader","If encryption is not intended, remove the cryptoKeyReaderClassName instead of leaving crypto half-configured"],"exampleFix":"// before\n// producerConf: { \"cryptoKeyReaderClassName\": \"com.acme.MyKeyReader\" } // no encryptionKeys\n// after\n// producerConf: { \"cryptoKeyReaderClassName\": \"com.acme.MyKeyReader\", \"encryptionKeys\": [\"my-public-key\"] }","handlingStrategy":"validation","validationCode":"if (isProducer && (conf.getEncryptionKeys() == null || conf.getEncryptionKeys().length == 0)) {\n    throw new IllegalStateException(\"Producer crypto requires encryptionKeys to be set\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    ValidatorUtils.validateCryptoKeyReader(conf, typePool, true);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Missing encryption key name\")) {\n        // set encryptionKeys in producer conf or drop the crypto config\n    }\n    throw e;\n}","preventionTips":["Always pair cryptoKeyReaderClassName with encryptionKeys in producer confs","Reuse a shared config template for encrypted sources","Verify key names exist in the key reader before submission"],"tags":["pulsar-functions","crypto","encryption","config-validation"],"backgroundTag":"missing-required-config","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}