apache/pulsar · error · IllegalArgumentException
Could not find source config class
Error message
Could not find source config class
What it means
Thrown by SourceConfigUtils.validateSourceConfig when a FunctionDefinition declares a custom source config class via getSourceConfigClass(), but Class.forName cannot load that class from the source function's classloader (ClassNotFoundException). Pulsar uses this class to deserialize and validate the user's 'configs' JSON, so a missing class aborts source-function validation.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SourceConfigUtils.java:525
return sourceConfig.getBatchSourceConfig() != null;
}
public static void validateBatchSourceConfigUpdate(BatchSourceConfig existingConfig, BatchSourceConfig newConfig) {
if (!existingConfig.getDiscoveryTriggererClassName().equals(newConfig.getDiscoveryTriggererClassName())) {
throw new IllegalArgumentException("DiscoverTriggerer class cannot be updated for batchsources");
}
}
public static void validateSourceConfig(SourceConfig sourceConfig, ValidatableFunctionPackage sourceFunction) {
try {
ConnectorDefinition defn = sourceFunction.getFunctionMetaData(ConnectorDefinition.class);
if (defn != null && defn.getSourceConfigClass() != null) {
Class<?> configClass =
Class.forName(defn.getSourceConfigClass(), true, sourceFunction.getClassLoader());
validateSourceConfig(sourceConfig, configClass);
}
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Could not find source config class");
}
}
public static void validateSourceConfig(SourceConfig sourceConfig, Class<?> configClass) {
try {
Object configObject =
ObjectMapperFactory.getMapper().getObjectMapper()
.convertValue(sourceConfig.getConfigs(), configClass);
if (configObject != null) {
ConfigValidation.validateConfig(configObject);
}
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Could not validate source config: " + e.getMessage());
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Verify the config class FQCN in the function/connector definition matches the actual class and that the class is packaged in the submitted jar
- Inspect the shaded/uber jar (jar tf) to confirm the .class file survived maven-shade relocation/exclusion filters
- Rebuild the connector with the config class in the same artifact the broker downloads, then resubmit the function
- If the config is generic (no custom class), clear/remove the sourceConfigClass declaration so validation skips Class.forName
Example fix
// before (definition references a class missing from the jar) FunctionDefinition defn = ...; // sourceConfigClass = "com.acme.MySourceConfig" (not packaged) // after // package com.acme.MySourceConfig in the connector jar, or: defn.setSourceConfigClass(null); // fall back to generic config validation
Defensive patterns
Strategy: try-catch
Validate before calling
// before submitting
String cls = defn.getSourceConfigClass();
if (cls != null) {
try {
Class.forName(cls, true, sourceFunction.getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Config class missing from jar: " + cls);
}
} Try / catch
try {
SourceConfigUtils.validateAndExtractDetails(...);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Could not find source config class")) {
// check jar contents and FunctionDefinition.sourceConfigClass, then resubmit
}
throw e;
} Prevention
- Run 'jar tf connector.jar | grep <ConfigClass>' before submitting
- Keep the config class in the same module/artifact as the connector
- Test connector registration in a dev cluster before production upload
When it happens
Trigger: Registering a source function whose FunctionDefinition.sourceConfigClass names a class that is not present in the uploaded jar / nar archive, or whose FQCN is misspelled or was renamed/refactored in a newer version of the connector.
Common situations: Building a custom source connector but forgetting to package the config class in the jar (e.g. excluded by shading rules); renaming the config class without updating the FunctionDefinition annotation/metadata; typos in the fully-qualified class name in the function metadata yaml.
Related errors
- Field '${name}' with value '${o}' does not implement ${class
- Cannot find/load class ${className}
- Source does not implement correct interface
- Config class not found: %s
- Sink does not implement correct interface
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/b24a12ffac9d6253.
Report an issue: GitHub.