apache/pulsar · error · RuntimeException

%s archive (%s) does not exist

Error message

%s archive (%s) does not exist

What it means

In extractClassLoader, LocalRunner resolves the user-code archive file from the function/source/sink config's archive location and checks Files.exists on it. When the archive path points to nothing on disk it throws RuntimeException '<Type> archive (<path>) does not exist'. The component type (Function/Source/Sink) is prefixed in the message.

Source

Thrown at pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions/LocalRunner.java:513

                classLoaderCreated = true;
            } else if (userCodeFile != null) {
                File file = new File(userCodeFile);
                if (!file.exists()) {
                    String errorMsg;
                    switch (componentType) {
                        case FUNCTION:
                            errorMsg = "User jar";
                            break;
                        case SOURCE:
                            errorMsg = "Source archive";
                            break;
                        case SINK:
                            errorMsg = "Sink archive";
                            break;
                        default:
                            throw new IllegalStateException("Unexpected value: " + componentType);
                    }
                    throw new RuntimeException(errorMsg + " (" + userCodeFile + ") does not exist");
                }
                classLoader = FunctionRuntimeCommon.getClassLoaderFromPackage(
                        componentType, className, file, narExtractionDirectory);
                classLoaderCreated = true;
            } else {
                if (!(runtimeEnv == null || runtimeEnv == RuntimeEnv.THREAD)) {
                    String errorMsg;
                    switch (componentType) {
                        case FUNCTION:
                            errorMsg = "The jar property must be specified in FunctionConfig.";
                            break;
                        case SOURCE:
                            errorMsg = "The archive property must be specified in SourceConfig.";
                            break;
                        case SINK:
                            errorMsg = "The archive property must be specified in SinkConfig.";
                            break;
                        default:

View on GitHub (pinned to 820761864e)

Solutions

  1. Correct the archive path in the config to point to the built jar/NAR
  2. Use an absolute path for the archive
  3. Build the target jar/NAR (mvn/gradle package) before starting the runner
  4. Verify with Files.exists(...) or ls before invoking start

Example fix

// before
sourceConfig.setArchive("target/my-source.nar");
// after
sourceConfig.setArchive(Paths.get(System.getProperty("user.dir"),
        "target/my-source.nar").toAbsolutePath().toString());
Defensive patterns

Strategy: validation

Validate before calling

String archive = sourceConfig.getArchive(); // or function/sink
if (archive == null || !java.nio.file.Files.exists(java.nio.file.Path.of(archive))) {
    throw new IllegalStateException("Archive does not exist: " + archive);
}

Try / catch

try {
    runner.start(true);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("does not exist")) {
        // build artifact or fix archive path, then retry with a new runner
    }
}

Prevention

When it happens

Trigger: FunctionConfig/SourceConfig/SinkConfig archive set to a non-existent path, a relative path resolved against a different working directory, or a jar deleted between config time and start time.

Common situations: Typos in archive path; building in one module while the target jar lives elsewhere; running localrun from a different working directory than expected; CI artifacts not built before the run.

Related errors


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