apache/pulsar · error · IllegalArgumentException

%s class %s must be in class path

Error message

%s class %s must be in class path

What it means

When the archive is a NAR and the connector class name is discovered automatically, getClassLoaderFromPackage loads the discovered connectorClassName from the NAR class loader. If loadClass throws ClassNotFoundException or NoClassDefFoundError, the library wraps it in this IllegalArgumentException stating the source/sink class must be on the class path.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionRuntimeCommon.java:101

                try {
                    if (componentType == FunctionDetails.ComponentType.FUNCTION) {
                        connectorClassName = FunctionUtils.getFunctionClass(narClassLoader);
                    } else if (componentType == FunctionDetails.ComponentType.SOURCE) {
                        connectorClassName = ConnectorUtils.getIOSourceClass(narClassLoader);
                    } else {
                        connectorClassName = ConnectorUtils.getIOSinkClass(narClassLoader);
                    }
                } catch (IOException e) {
                    throw new IllegalArgumentException(String.format("Failed to extract %s class from archive",
                            componentType.toString().toLowerCase()), e);
                }

                try {
                    narClassLoader.loadClass(connectorClassName);
                    keepNarClassLoader = true;
                    return narClassLoader;
                } catch (ClassNotFoundException | NoClassDefFoundError e) {
                    throw new IllegalArgumentException(String.format("%s class %s must be in class path",
                            FunctionCommon.capFirstLetter(componentType), connectorClassName), e);
                }

            } else {
                // if connector class name is provided, we need to try to load it as a JAR and as a NAR.
                if (jarClassLoader != null) {
                    try {
                        jarClassLoader.loadClass(connectorClassName);
                        keepJarClassLoader = true;
                        return jarClassLoader;
                    } catch (ClassNotFoundException | NoClassDefFoundError e) {
                        // class not found in JAR try loading as a NAR and searching for the class
                        if (narClassLoader != null) {

                            try {
                                narClassLoader.loadClass(connectorClassName);
                                keepNarClassLoader = true;
                                return narClassLoader;

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the NAR: confirm the class file exists at the declared package path inside the archive
  2. Check the rejected-classes / missing dependency in the nested NoClassDefFoundError cause and add that dependency to the NAR
  3. Rebuild the NAR with the maven-shade-plugin properly bundling (not excluding) connector classes
  4. Verify the class name in META-INF/services matches the actual fully qualified class name

Example fix

// before: shaded jar excludes implementation classes
<artifactSet><excludes><exclude>com.mycorp:connector-impl</exclude></excludes></artifactSet>
// after: keep connector implementation in the NAR
<artifactSet><excludes></excludes></artifactSet>
Defensive patterns

Strategy: validation

Validate before calling

try (URLClassLoader cl = new URLClassLoader(new URL[]{archiveUrl}, parentCl)) {
  cl.loadClass(connectorClassName); // fails fast with the real cause before registration
}

Try / catch

try {
  createFunction(...);
} catch (IllegalArgumentException e) {
  log.error("Connector class {} not loadable from NAR: {}", connectorClassName, e.getCause(), e);
}

Prevention

When it happens

Trigger: NAR's connector descriptor names a class (e.g. via ConnectorUtils.getIOSourceClass) but the class fails to load from the NAR class loader — the class file is missing from the archive, fails to initialize statically, or its dependencies are absent.

Common situations: The declared class was renamed or removed without updating META-INF/services; the NAR excludes transitive dependencies at shade time; NoClassDefFoundError caused by a static initializer failure of the connector class.

Related errors


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