elastic/elasticsearch · error · InvalidUserDataException
Missing 'classesDirs' or 'classpath' property.
Error message
Missing 'classesDirs' or 'classpath' property.
What it means
Thrown by CacheCacheableTestFixtures.createClassLoader(FileCollection) when the classpath argument is null. The task needs a classpath to build a URLClassLoader for loading/processing test fixtures; a null classpath means the task was wired without its required 'classpath' (or 'classesDirs') property. It is a configuration-time guard, not a runtime IO failure.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/packer/CacheCacheableTestFixtures.java:114
e.printStackTrace();
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Close the classloader to free resources:
try {
if (urlLoader != null) urlLoader.close();
} catch (IOException ioe) {
// getLogger().warn("Cannot close classloader: ".concat(ioe.toString()));
}
}
}
private URLClassLoader createClassLoader(FileCollection classpath) {
if (classpath == null) {
throw new InvalidUserDataException("Missing 'classesDirs' or 'classpath' property.");
}
final Set<File> cpElements = new LinkedHashSet<>();
cpElements.addAll(classpath.getFiles());
final URL[] urls = new URL[cpElements.size()];
try {
int i = 0;
for (final File cpElement : cpElements) {
urls[i++] = cpElement.toURI().toURL();
}
assert i == urls.length;
} catch (MalformedURLException mfue) {
throw new InvalidUserDataException("Failed to build classpath URLs.", mfue);
}
return URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
}
View on GitHub (pinned to db6a809a66)
Solutions
- Find the task registration (search for the task type / the register call) and confirm classpath and classesDirs are assigned.
- Set classpath from the relevant source set: fixturesTask.classpath = sourceSets.fixtures.runtimeClasspath.
- If the task genuinely needs no classpath, switch to an overload that does not create a classloader, or guard createClassLoader against null callers.
- After fixing, run the specific task with --rerun-tasks to confirm.
Example fix
// before
// task not given a classpath
// after
tasks.named('cacheCacheableTestFixtures', CacheCacheableTestFixtures) {
classpath = sourceSets.test.runtimeClasspath
} Defensive patterns
Strategy: validation
Validate before calling
// In the task registration, assert the property is wired before execution
tasks.named('cacheCacheableTestFixtures').configure(t -> {
if (((CacheCacheableTestFixtures) t).getClasspath() == null) {
throw new InvalidUserDataException("cacheCacheableTestFixtures requires 'classpath' to be set");
}
}); Prevention
- Treat required task inputs as mandatory: always set them in the registration block.
- Add a configuration-time sanity check that fails fast with a clear message.
- When copying a task from another module, audit its required properties.
When it happens
Trigger: A build script or plugin registers a CacheCacheableTestFixtures (or equivalent) task but never calls .classpath(...) / .classesDirs(...), so the property stays null when createClassLoader runs at execution time.
Common situations: Copying a task registration from another project and forgetting to wire the classpath; renaming a property during a refactor without updating the registration; a custom subproject that opts into cacheable test fixtures but has no test source set to derive the classpath from.
Related errors
- Failed to build classpath URLs.
- Cannot load VersionPropertiesBuildService
- Cannot resolve minimum compiler version via VersionPropertie
- Elasticsearch version is missing from properties.
- Expected elasticsearch version to be numbers only of the for
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/194cb55b279c5aa7.
Report an issue: GitHub.