apache/flink · critical · RuntimeException

Found {optJarPath.size()} %s jar.

Error message

Found {optJarPath.size()} %s jar.

What it means

Thrown when the number of jars matching the target name in the opt directory is not exactly one. If zero are found, the jar is missing from the installation; if more than one, there are duplicates. Note: the message format has a bug — it uses String.format with a hardcoded concatenation and an unused %s placeholder, producing a garbled message like 'Found 2 %s jar.'.

Source

Thrown at flink-clients/src/main/java/org/apache/flink/client/program/PackagedProgramUtils.java:274

                    new SimpleFileVisitor<Path>() {
                        @Override
                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                                throws IOException {
                            FileVisitResult result = super.visitFile(file, attrs);
                            if (file.getFileName().toString().startsWith(jarName)) {
                                optJarPath.add(file);
                            }
                            return result;
                        }
                    });
        } catch (IOException e) {
            throw new RuntimeException(
                    "Exception encountered during finding the flink-python jar. This should not happen.",
                    e);
        }

        if (optJarPath.size() != 1) {
            throw new RuntimeException(
                    String.format("Found " + optJarPath.size() + " %s jar.", jarName));
        }

        try {
            return optJarPath.get(0).toUri().toURL();
        } catch (MalformedURLException e) {
            throw new RuntimeException("URL is invalid. This should not happen.", e);
        }
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. List jars in $FLINK_HOME/opt and ensure exactly one matches the target name prefix.
  2. Remove duplicate jars (keep only the version matching your Flink distribution).
  3. If zero found, download/reinstall the correct flink-python jar for your Flink version.
  4. Avoid manually copying jars with similar names into opt/.

Example fix

# before: two flink-python jars present
ls $FLINK_HOME/opt/flink-python*
# flink-python_2.12-1.17.jar  flink-python_2.12-1.18.jar

# after: keep only the matching version
rm $FLINK_HOME/opt/flink-python_2.12-1.17.jar
Defensive patterns

Strategy: validation

Validate before calling

String optDir = System.getenv(ConfigConstants.ENV_FLINK_OPT_DIR);
File[] matches = new File(optDir).listFiles((d, name) -> name.startsWith(jarName));
if (matches == null || matches.length != 1) {
    throw new IllegalStateException("Expected exactly one " + jarName + " jar in " + optDir);
}

Try / catch

try {
    // code that triggers getOptJar
} catch (RuntimeException e) {
    if (e.getMessage().contains("jar")) {
        // list and deduplicate jars in opt/
    }
    throw e;
}

Prevention

When it happens

Trigger: getOptJar finds zero or more than one jar whose filename starts with the target name (e.g., 'flink-python'). Triggered during PyFlink initialization when locating the python connector jar.

Common situations: Multiple versions of flink-python jar left in opt/ after an upgrade, or the jar was removed/renamed. Also seen with custom distributions that bundle extra jars with overlapping prefixes.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/c8c5cb0adba952c2. Report an issue: GitHub.