elastic/elasticsearch · error · IllegalArgumentException

unrecognized classpath entry: {}

Error message

unrecognized classpath entry: {}

What it means

Thrown by GenerateTestBuildInfoTask.buildLocationList when a classpath code-location entry that exists on disk is neither a .jar file (matching JAR_DESCRIPTOR_SUFFIX) nor a directory. The task only knows how to scan jars and directories for test location metadata, so any other file shape is rejected.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/plugin/GenerateTestBuildInfoTask.java:133

     *                            whose name will be unique within its {@link ClassLoader} at run time.
     */
    record Location(String module, String representativeClass) {}

    /**
     * Build the list of {@link Location}s for all {@link #getCodeLocations() code locations}.
     * There are different methods for finding these depending on if the
     * classpath entry is a jar or a directory
     */
    private List<Location> buildLocationList() throws IOException {
        List<Location> locations = new ArrayList<>();
        for (File file : getCodeLocations().get().getFiles()) {
            if (file.exists()) {
                if (file.getName().endsWith(JAR_DESCRIPTOR_SUFFIX)) {
                    extractLocationsFromJar(file, locations);
                } else if (file.isDirectory()) {
                    extractLocationsFromDirectory(file, locations);
                } else {
                    throw new IllegalArgumentException("unrecognized classpath entry: " + file);
                }
            }
        }
        return List.copyOf(locations);
    }

    /**
     * find the first class and module when the class path entry is a jar
     */
    private void extractLocationsFromJar(File file, List<Location> locations) throws IOException {
        try (JarFile jarFile = new JarFile(file)) {
            var className = extractClassNameFromJar(jarFile);

            if (className.isPresent()) {
                String moduleName = extractModuleNameFromJar(file, jarFile);
                locations.add(new Location(moduleName, className.get()));
            }
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the offending file path printed in the message — confirm it is unexpected, then fix the configuration feeding getCodeLocations().
  2. Ensure all code-location entries are either compiled output directories (classes dirs) or .jar artifacts.
  3. Run with --rerun-tasks and clean to drop stale cache entries that may have produced a non-jar file.
  4. If you must point at an archive, package it as a .jar so the JAR_DESCRIPTOR_SUFFIX branch handles it.

Example fix

// before
testBuildInfo {
  codeLocations.from files('build/libs/app.zip')  // not a jar, not a dir
}

// after
testBuildInfo {
  codeLocations.from sourceSets.main.output, configurations.runtimeClasspath
}
Defensive patterns

Strategy: validation

Validate before calling

for (File f : codeLocationFiles) {
    if (!f.exists()) continue;
    if (!f.getName().endsWith(".jar") && !f.isDirectory()) {
        throw new IllegalArgumentException("Refusing to add non-jar non-dir classpath entry: " + f);
    }
}

Prevention

When it happens

Trigger: getCodeLocations().get().getFiles() returns a File that exists, does not end in .jar, and is not a directory (e.g. a .class file, a .zip, a broken symlink resolved to a non-jar file, a flat file passed as a code location).

Common situations: Misconfiguring a test task's classpath to point at a loose file or a non-jar archive; a stale build cache returning a placeholder file; symlinks in the build dir resolving to odd targets.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/5acb850cb76d22be. Report an issue: GitHub.