apache/pulsar · error · IllegalStateException

The function registration references a different set of jar

Error message

The function registration references a different set of jar files than  previous registrations for this function : old = ${jarFiles}, new = ${requiredJarFiles}

What it means

FunctionCacheEntry.register() enforces that every registration of the same function (same function ID/entry) uses exactly the same set of jar files as previously registered instances. This IllegalStateException is thrown when the requiredJarFiles passed in differ from the jarFiles already recorded (different size or different contents), indicating inconsistent function metadata across instances of the same function.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/functioncache/FunctionCacheEntry.java:90

                .narFile(new File(narArchive))
                .extractionDirectory(narExtractionDirectory)
                .parentClassLoader(rootClassLoader)
                .build();
        this.classpaths = Collections.emptySet();
        this.jarFiles = Collections.singleton(narArchive);
        this.executionHolders = new HashSet<>(Collections.singleton(initialInstanceId));
    }

    boolean isInstanceRegistered(String iid) {
        return executionHolders.contains(iid);
    }

    public void register(String eid,
                         Collection<String> requiredJarFiles,
                         Collection<URL> requiredClassPaths) {
        if (jarFiles.size() != requiredJarFiles.size()
            || !new HashSet<>(requiredJarFiles).containsAll(jarFiles)) {
            throw new IllegalStateException(
                "The function registration references a different set of jar files than "
                + " previous registrations for this function : old = " + jarFiles
                + ", new = " + requiredJarFiles);
        }

        if (classpaths.size() != requiredClassPaths.size()
            || !requiredClassPaths.stream().map(URL::toString).collect(Collectors.toSet())
                .containsAll(classpaths)) {
            throw new IllegalStateException(
                "The function registration references a different set of classpaths than "
                + " previous registrations for this function : old = " + classpaths
                + ", new = " + requiredClassPaths);
        }

        this.executionHolders.add(eid);
    }

    public boolean unregister(String eid) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Delete/unregister all existing instances for this function (FunctionCacheManagerImpl.removeFunction) so a fresh FunctionCacheEntry is created, then register with the new jar set.
  2. Ensure every instance of the same function uses the identical jar file paths (same downloaded archive location).
  3. If the function was updated, trigger a full restart of the function instances so the cache entry is recreated.

Example fix

// before: re-registering an updated jar against the same entry
CacheEntry cache = cacheManager.getFunctionCacheEntry(tenant, namespace, name);
cache.register(eid, newJars, classpaths); // IllegalStateException: different set of jar files
// after
cacheManager.removeFunction(tenant, namespace, name);
cacheManager.getFunctionCacheEntry(tenant, namespace, name, ...).register(eid, newJars, classpaths);
Defensive patterns

Strategy: try-catch

Validate before calling

FunctionCacheEntry existing = cacheManager.getFunctionCacheEntry(tenant, namespace, name);
if (existing != null && !existingJarPaths.equals(requiredJarFiles)) {
    cacheManager.removeFunction(tenant, namespace, name); // rebuild entry with the new jar set
}

Try / catch

try {
    entry.register(eid, requiredJarFiles, requiredClassPaths);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("different set of jar files")) {
        cacheManager.removeFunction(tenant, namespace, name);
        // recreate entry and register again
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling register(eid, requiredJarFiles, requiredClassPaths) on an existing FunctionCacheEntry (via registerFunctionInstance / registerFunctionInstanceWithArchive in FunctionCacheManagerImpl) where requiredJarFiles is not equal to the set recorded from earlier registrations — e.g. a jar path changed, was added, or removed for a second instance of the same function.

Common situations: Updating a function's jar while old instances are still registered (restart with new package location/version); different worker instances resolving the function package to different paths (local vs distributed download dir); a function update that changed the archive while the cache entry was reused; mixing NAR and non-NAR package locations.

Related errors


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