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
- Inspect the offending file path printed in the message — confirm it is unexpected, then fix the configuration feeding getCodeLocations().
- Ensure all code-location entries are either compiled output directories (classes dirs) or .jar artifacts.
- Run with --rerun-tasks and clean to drop stale cache entries that may have produced a non-jar file.
- 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
- Only wire compiled output dirs and .jar artifacts into codeLocations.
- Avoid loose .class files or non-jar archives in test classpaths.
- Use Gradle's sourceSets / configurations rather than hand-built file collections.
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
- classname is a required setting for esplugin
- classname is a forbidden for stable esplugin
- invalid deploymentTarget '{}', expected one of {}
- Number of nodes should be >= 1 but was {} for {}
- Cannot shrink {} to have {} nodes as it already has {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/5acb850cb76d22be.
Report an issue: GitHub.