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

  1. Verify the config class FQCN in the function/connector definition matches the actual class and that the class is packaged in the submitted jar
  2. Inspect the shaded/uber jar (jar tf) to confirm the .class file survived maven-shade relocation/exclusion filters
  3. Rebuild the connector with the config class in the same artifact the broker downloads, then resubmit the function
  4. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/b24a12ffac9d6253. Report an issue: GitHub.