elastic/elasticsearch · error · GradleException
expected modules ${listToString(EXPECTED_ES_SERVER_MODULES)}
Error message
expected modules ${listToString(EXPECTED_ES_SERVER_MODULES)},
actual modules ${listToString(actualESModules)} What it means
Thrown as GradleException by assertAllModulesPresent() when the set of ES modules discovered by ModuleFinder.of(libPath).findAll() (filtered to names starting 'org.elasticsearch') does not exactly equal EXPECTED_ES_SERVER_MODULES. This is an exact-set equality check — any added, removed, or renamed module fails it. The constant list is the authoritative manifest of modules that must ship in the ES server distribution.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionModuleCheckTaskProvider.java:132
try (var s = Files.walk(libPath, 1)) {
s.filter(Files::isRegularFile).filter(isESJar).filter(isNotExcluded).sorted().forEach(path -> {
try (JarFile jf = new JarFile(path.toFile())) {
JarEntry entry = jf.getJarEntry(MODULE_INFO);
if (entry == null) {
throw new GradleException(MODULE_INFO + " no found in " + path);
}
} catch (IOException e) {
throw new GradleException("Failed when reading jar file " + path, e);
}
});
}
}
/** Checks that all expected Elasticsearch modules are present. */
private static void assertAllModulesPresent(Path libPath) {
List<String> actualESModules = ModuleFinder.of(libPath).findAll().stream().filter(isESModule).map(toName).sorted().toList();
if (actualESModules.equals(EXPECTED_ES_SERVER_MODULES) == false) {
throw new GradleException(
"expected modules " + listToString(EXPECTED_ES_SERVER_MODULES) + ", \nactual modules " + listToString(actualESModules)
);
}
}
// ####: eventually assert hashes, etc
static String listToString(List<String> list) {
return list.stream().sorted().collect(joining("\n ", "[\n ", "]"));
}
}
View on GitHub (pinned to db6a809a66)
Solutions
- Compare the 'expected' vs 'actual' lists in the error message — the diff shows exactly which module was added or removed.
- If a module was legitimately added, append its name to EXPECTED_ES_SERVER_MODULES in this file (line 52).
- If a module is unexpectedly missing, investigate why its jar didn't build or isn't in lib/ (check the jar task and distribution assembly).
- If a module was renamed, update both the module-info.java and EXPECTED_ES_SERVER_MODULES to the new name.
Example fix
// before: new module org.elasticsearch.newfeature built but not in expected list
// throws: expected modules [...], actual modules [...org.elasticsearch.newfeature...]
// after: add the module name to the expected list
private static final List<String> EXPECTED_ES_SERVER_MODULES = List.of(
// ...
"org.elasticsearch.newfeature",
"org.elasticsearch.xcontent"
); Defensive patterns
Strategy: validation
Validate before calling
List<String> actual = ModuleFinder.of(libPath).findAll().stream()
.map(m -> m.descriptor().name()).filter(n -> n.startsWith("org.elasticsearch")).sorted().toList();
List<String> missing = new ArrayList<>(EXPECTED_ES_SERVER_MODULES); missing.removeAll(actual);
List<String> extra = new ArrayList<>(actual); extra.removeAll(EXPECTED_ES_SERVER_MODULES);
if (missing.isEmpty() == false || extra.isEmpty() == false) {
System.err.println("Module mismatch — missing: " + missing + ", extra: " + extra);
} Prevention
- Update EXPECTED_ES_SERVER_MODULES whenever a module is added, removed, or renamed.
- Keep the list alphabetically sorted to match the sorted comparison.
- Run checkModules after any module-info.java change in the build.
- Review module manifest changes in code review for distribution impact.
When it happens
Trigger: assertAllModulesPresent (line 129) collects actual module names, sorts, and compares with .equals against the static EXPECTED_ES_SERVER_MODULES list (line 52). A new module added without updating the list, a module renamed, or a module missing from the build all cause inequality and throw.
Common situations: A new ES module was added to the build (e.g., org.elasticsearch.newfeature) but EXPECTED_ES_SERVER_MODULES wasn't updated; a module was renamed or removed; a module failed to build and is absent from lib/; a module was accidentally split into two.
Related errors
- module-info.class no found in ${path}
- Automatic-Module-Name: {e.getMessage()}
- automatic module without a manifest name is not supported, f
- unexpected jar name: {jarName}
- Cannot set Elasticsearch Distribution type to ${type}. Type
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/33ee78d8bdcbf553.
Report an issue: GitHub.