{"record":{"id":"17d9cd84c072e837","repo":"apache/pulsar","slug":"s-class-s-must-be-in-class-path","errorCode":null,"errorMessage":"%s class %s must be in class path","messagePattern":"(.+?) class (.+?) must be in class path","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionRuntimeCommon.java","lineNumber":101,"sourceCode":"                try {\n                    if (componentType == FunctionDetails.ComponentType.FUNCTION) {\n                        connectorClassName = FunctionUtils.getFunctionClass(narClassLoader);\n                    } else if (componentType == FunctionDetails.ComponentType.SOURCE) {\n                        connectorClassName = ConnectorUtils.getIOSourceClass(narClassLoader);\n                    } else {\n                        connectorClassName = ConnectorUtils.getIOSinkClass(narClassLoader);\n                    }\n                } catch (IOException e) {\n                    throw new IllegalArgumentException(String.format(\"Failed to extract %s class from archive\",\n                            componentType.toString().toLowerCase()), e);\n                }\n\n                try {\n                    narClassLoader.loadClass(connectorClassName);\n                    keepNarClassLoader = true;\n                    return narClassLoader;\n                } catch (ClassNotFoundException | NoClassDefFoundError e) {\n                    throw new IllegalArgumentException(String.format(\"%s class %s must be in class path\",\n                            FunctionCommon.capFirstLetter(componentType), connectorClassName), e);\n                }\n\n            } else {\n                // if connector class name is provided, we need to try to load it as a JAR and as a NAR.\n                if (jarClassLoader != null) {\n                    try {\n                        jarClassLoader.loadClass(connectorClassName);\n                        keepJarClassLoader = true;\n                        return jarClassLoader;\n                    } catch (ClassNotFoundException | NoClassDefFoundError e) {\n                        // class not found in JAR try loading as a NAR and searching for the class\n                        if (narClassLoader != null) {\n\n                            try {\n                                narClassLoader.loadClass(connectorClassName);\n                                keepNarClassLoader = true;\n                                return narClassLoader;","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionRuntimeCommon.java#L83-L119","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the NAR: confirm the class file exists at the declared package path inside the archive","Check the rejected-classes / missing dependency in the nested NoClassDefFoundError cause and add that dependency to the NAR","Rebuild the NAR with the maven-shade-plugin properly bundling (not excluding) connector classes","Verify the class name in META-INF/services matches the actual fully qualified class name"],"exampleFix":"// before: shaded jar excludes implementation classes\n<artifactSet><excludes><exclude>com.mycorp:connector-impl</exclude></excludes></artifactSet>\n// after: keep connector implementation in the NAR\n<artifactSet><excludes></excludes></artifactSet>","handlingStrategy":"validation","validationCode":"try (URLClassLoader cl = new URLClassLoader(new URL[]{archiveUrl}, parentCl)) {\n  cl.loadClass(connectorClassName); // fails fast with the real cause before registration\n}","typeGuard":null,"tryCatchPattern":"try {\n  createFunction(...);\n} catch (IllegalArgumentException e) {\n  log.error(\"Connector class {} not loadable from NAR: {}\", connectorClassName, e.getCause(), e);\n}","preventionTips":["Confirm the class file exists inside the NAR before upload","Do not exclude connector implementation classes in maven-shade-plugin config","Read the full cause chain — NoClassDefFoundError often masks missing transitive dependencies"],"tags":["pulsar-functions","classnotfound","nar-archive","io-connector"],"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"}