{"record":{"id":"e9a0ba186d02e0eb","repo":"apache/pulsar","slug":"the-function-registration-references-a-different-s-e9a0ba","errorCode":null,"errorMessage":"The function registration references a different set of classpaths than  previous registrations for this function : old = ${classpaths}, new = ${requiredClassPaths}","messagePattern":"The function registration references a different set of classpaths than  previous registrations for this function : old = (.+?), new = (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/functioncache/FunctionCacheEntry.java","lineNumber":99,"sourceCode":"    boolean isInstanceRegistered(String iid) {\n        return executionHolders.contains(iid);\n    }\n\n    public void register(String eid,\n                         Collection<String> requiredJarFiles,\n                         Collection<URL> requiredClassPaths) {\n        if (jarFiles.size() != requiredJarFiles.size()\n            || !new HashSet<>(requiredJarFiles).containsAll(jarFiles)) {\n            throw new IllegalStateException(\n                \"The function registration references a different set of jar files than \"\n                + \" previous registrations for this function : old = \" + jarFiles\n                + \", new = \" + requiredJarFiles);\n        }\n\n        if (classpaths.size() != requiredClassPaths.size()\n            || !requiredClassPaths.stream().map(URL::toString).collect(Collectors.toSet())\n                .containsAll(classpaths)) {\n            throw new IllegalStateException(\n                \"The function registration references a different set of classpaths than \"\n                + \" previous registrations for this function : old = \" + classpaths\n                + \", new = \" + requiredClassPaths);\n        }\n\n        this.executionHolders.add(eid);\n    }\n\n    public boolean unregister(String eid) {\n        this.executionHolders.remove(eid);\n        return this.executionHolders.isEmpty();\n    }\n\n    @Override\n    public void close() {\n        try {\n            classLoader.close();\n        } catch (IOException e) {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/functioncache/FunctionCacheEntry.java#L81-L117","documentation":"FunctionCacheEntry.register() also verifies that the extra classpath URLs (requiredClassPaths) match those recorded from prior registrations for the same function entry. This IllegalStateException is thrown when the set of classpath URLs differs (in size or contents) from previously registered classpaths — the same function must present a consistent classpath across all its instances.","triggerScenarios":"Calling register(eid, requiredJarFiles, requiredClassPaths) on a FunctionCacheEntry that already holds classpaths, where the new URL set is not equal to the old set (URLs compared by string form).","commonSituations":"A function update adding/removing extra classpath dependencies while old instances remain; URL string differences (file:// vs path form, trailing slash, host differences) causing set inequality despite the same file; different workers computing different classpath URLs for the same function.","solutions":["Remove the function's cache entry (removeFunction) and re-register fresh with the new classpath set.","Ensure identical, canonical URL strings (same scheme/path) are produced for every instance registration.","Restart all function instances after a dependency change so the entry is rebuilt."],"exampleFix":"// before\ncache.register(eid, jars, Arrays.asList(new URL(\"file:/extra-dep.jar\"))); // old entry had different URLs\n// after\ncacheManager.removeFunction(tenant, namespace, name);\nvar freshEntry = cacheManager.getFunctionCacheEntry(tenant, namespace, name, null, null, null, null, null, null, false, null);\nfreshEntry.register(eid, jars, Arrays.asList(new URL(\"file:/extra-dep.jar\")));","handlingStrategy":"try-catch","validationCode":"FunctionCacheEntry existing = cacheManager.getFunctionCacheEntry(tenant, namespace, name);\nif (existing != null && !existingClasspathStrings.equals(requiredClassPaths.stream().map(URL::toString).collect(Collectors.toSet()))) {\n    cacheManager.removeFunction(tenant, namespace, name);\n}","typeGuard":null,"tryCatchPattern":"try {\n    entry.register(eid, requiredJarFiles, requiredClassPaths);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"different set of classpaths\")) {\n        cacheManager.removeFunction(tenant, namespace, name);\n        // recreate entry and register again\n    } else {\n        throw e;\n    }\n}","preventionTips":["Canonicalize classpath URLs (same scheme, path, no trailing slashes) before registration.","Rebuild the cache entry whenever the classpath dependency set changes.","Keep classpath computation code shared so all instances derive identical URLs."],"tags":["pulsar-functions","function-cache","classloader","state"],"backgroundTag":"stale-cache-entry","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"}