{"record":{"id":"96d2fef3322c80c1","repo":"apache/pulsar","slug":"could-not-find-sink-config-class","errorCode":null,"errorMessage":"Could not find sink config class","messagePattern":"Could not find sink config class","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java","lineNumber":752,"sourceCode":"        }\n        if (newConfig.getTransformFunctionConfig() != null) {\n            mergedConfig.setTransformFunctionConfig(newConfig.getTransformFunctionConfig());\n        }\n        if (newConfig.getSourceSubscriptionPosition() != null) {\n            mergedConfig.setSourceSubscriptionPosition(newConfig.getSourceSubscriptionPosition());\n        }\n        return mergedConfig;\n    }\n\n    public static void validateSinkConfig(SinkConfig sinkConfig, ValidatableFunctionPackage sinkFunction) {\n        try {\n            ConnectorDefinition defn = sinkFunction.getFunctionMetaData(ConnectorDefinition.class);\n            if (defn != null && defn.getSinkConfigClass() != null) {\n                Class<?> configClass = Class.forName(defn.getSinkConfigClass(), true, sinkFunction.getClassLoader());\n                validateSinkConfig(sinkConfig, configClass);\n            }\n        } catch (ClassNotFoundException e) {\n            throw new IllegalArgumentException(\"Could not find sink config class\", e);\n        }\n    }\n\n    public static void validateSinkConfig(SinkConfig sinkConfig, Class<?> configClass) {\n        try {\n            Object configObject =\n                    ObjectMapperFactory.getMapper().getObjectMapper()\n                            .convertValue(sinkConfig.getConfigs(), configClass);\n            if (configObject != null) {\n                ConfigValidation.validateConfig(configObject);\n            }\n        } catch (IllegalArgumentException e) {\n            throw new IllegalArgumentException(\"Could not validate sink config: \" + e.getMessage());\n        }\n    }\n}\n","sourceCodeStart":734,"sourceCodeEnd":769,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java#L734-L769","documentation":"Thrown by SinkConfigUtils.validateAndExtractDetails when the connector definition declares a sinkConfigClass that cannot be loaded via Class.forName using the sink function's classloader (ClassNotFoundException is rewrapped as IllegalArgumentException). The connector's custom config class is required to validate the sink's user-provided configs.","triggerScenarios":"Updating/submitting a sink backed by a connector whose ConnectorDefinition.getSinkConfigClass() names a class missing from the classpath/NAR, e.g. wrong NAR file version or class renamed in the connector.","commonSituations":"Custom connector NAR without the config class packaged; connector upgraded and config class renamed while old configs reference the old FQCN; typo in the sinkConfigClass declared in the connector's yaml.","solutions":["Ensure the connector NAR contains the declared sinkConfigClass and matches the deployed version","Correct the sinkConfigClass name in the connector definition (META-INF/services/connector yaml)","Check the sinkFunction classloader includes the connector's jar; restart with the correct NAR"],"exampleFix":"// connector definition yaml\n// before\nsinkConfigClass: com.example.OldSinkConfig\n// after\nsinkConfigClass: com.example.MySinkConfig // class actually packaged in the NAR","handlingStrategy":"try-catch","validationCode":"try {\n    Class.forName(sinkConfigClassFqcn, true, fnClassLoader);\n} catch (ClassNotFoundException e) {\n    throw new IllegalStateException(\"Connector NAR is missing config class \" + sinkConfigClassFqcn);\n}","typeGuard":null,"tryCatchPattern":"try {\n    admin.sinks().updateSink(tenant, namespace, cfg, null);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Could not find sink config class\")) { /* redeploy correct connector NAR */ }\n    else throw e;\n}","preventionTips":["Verify the connector NAR packages the class named in sinkConfigClass","Keep connector definition yaml in sync with packaged class names across versions","Test connector deployment in CI before production updates"],"tags":["pulsar","functions","connector","classpath","reflection"],"backgroundTag":"class-not-found","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"}