apache/pulsar · error · RuntimeException

Config class not found: %s

Error message

Config class not found: %s

What it means

The function declares a typed config (configClassName in FunctionDetails) but Class.forName cannot load that class from the component classloader during instance construction. The runtime needs the config class to reflect over its bean properties and inject user configuration, so it fails hard wrapping the ClassNotFoundException.

Source

Thrown at pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceRunnable.java:1043

        interpolateSecretsIntoConfigs(secretsProvider, config);

        if (instanceConfig.isIgnoreUnknownConfigFields() && componentClassLoader instanceof NarClassLoader) {
            final String configClassName;
            if (componentType == FunctionDetails.ComponentType.SOURCE) {
                configClassName = ConnectorUtils
                        .getConnectorDefinition((NarClassLoader) componentClassLoader).getSourceConfigClass();
            } else {
                configClassName =  ConnectorUtils
                        .getConnectorDefinition((NarClassLoader) componentClassLoader).getSinkConfigClass();
            }
            if (configClassName != null) {

                Class<?> configClass;
                try {
                    configClass = Class.forName(configClassName,
                            true, Thread.currentThread().getContextClassLoader());
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException("Config class not found: " + configClassName, e);
                }
                final List<String> allFields = BeanPropertiesReader.getBeanProperties(configClass);

                for (String s : config.keySet()) {
                    if (!allFields.contains(s)) {
                        log.error()
                                .attr("field", s)
                                .attr("componentType", componentType)
                                .attr("configClass", configClass)
                                .log("Field not defined in the configuration,"
                                        + " the field will be ignored");
                        config.remove(s);
                    }
                }
            }
        }
        return config;
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify the exact fully-qualified class name in the function config matches a class present in the uploaded JAR (unzip -l function.jar)
  2. If using maven-shade, ensure the config class package is not relocated, or update the config className accordingly
  3. Rebuild and redeploy the JAR containing the config class before submitting/updating the function
  4. For nested classes use the binary name with $ (com.example.Foo$Config)

Example fix

// before (function config)
{"className":"com.acme.MySource","configClassName":"com.acme.MyOldSourceConfig"}
// after
{"className":"com.acme.MySource","configClassName":"com.acme.MySourceConfig"}
Defensive patterns

Strategy: validation

Validate before calling

String cn = details.getConfigClassName();
Class.forName(cn, true, functionClassLoader); // fails fast before submission

Try / catch

try { submitFunction(cfg); }
catch (RuntimeException e) {
  if (e.getMessage().startsWith("Config class not found")) {
    log.error("Verify configClassName exists in the uploaded JAR", e);
  }
}

Prevention

When it happens

Trigger: The className string in the function config doesn't match the fully-qualified name of a class in the function JAR; the JAR containing the config class wasn't uploaded; the class is in the uber JAR but shaded/moved by a relocation rule; typo in package name.

Common situations: Renaming the config class package without redeploying the JAR; building the function with shading that relocates the config class; specifying an inner class name with wrong separator (Foo.Bar vs Foo$Bar); deploying a source/sink JAR that omits the config class.

Related errors


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