{"record":{"id":"33ee78d8bdcbf553","repo":"elastic/elasticsearch","slug":"expected-modules-listtostring-expected-es-server","errorCode":null,"errorMessage":"expected modules ${listToString(EXPECTED_ES_SERVER_MODULES)}, \nactual modules ${listToString(actualESModules)}","messagePattern":"expected modules (.+?), \nactual modules (.+?)","errorType":"validation","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionModuleCheckTaskProvider.java","lineNumber":132,"sourceCode":"        try (var s = Files.walk(libPath, 1)) {\n            s.filter(Files::isRegularFile).filter(isESJar).filter(isNotExcluded).sorted().forEach(path -> {\n                try (JarFile jf = new JarFile(path.toFile())) {\n                    JarEntry entry = jf.getJarEntry(MODULE_INFO);\n                    if (entry == null) {\n                        throw new GradleException(MODULE_INFO + \" no found in \" + path);\n                    }\n                } catch (IOException e) {\n                    throw new GradleException(\"Failed when reading jar file \" + path, e);\n                }\n            });\n        }\n    }\n\n    /** Checks that all expected Elasticsearch modules are present. */\n    private static void assertAllModulesPresent(Path libPath) {\n        List<String> actualESModules = ModuleFinder.of(libPath).findAll().stream().filter(isESModule).map(toName).sorted().toList();\n        if (actualESModules.equals(EXPECTED_ES_SERVER_MODULES) == false) {\n            throw new GradleException(\n                \"expected modules \" + listToString(EXPECTED_ES_SERVER_MODULES) + \", \\nactual modules \" + listToString(actualESModules)\n            );\n        }\n    }\n\n    // ####: eventually assert hashes, etc\n\n    static String listToString(List<String> list) {\n        return list.stream().sorted().collect(joining(\"\\n  \", \"[\\n  \", \"]\"));\n    }\n}\n","sourceCodeStart":114,"sourceCodeEnd":144,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionModuleCheckTaskProvider.java#L114-L144","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: new module org.elasticsearch.newfeature built but not in expected list\n// throws: expected modules [...], actual modules [...org.elasticsearch.newfeature...]\n\n// after: add the module name to the expected list\nprivate static final List<String> EXPECTED_ES_SERVER_MODULES = List.of(\n    // ...\n    \"org.elasticsearch.newfeature\",\n    \"org.elasticsearch.xcontent\"\n);","handlingStrategy":"validation","validationCode":"List<String> actual = ModuleFinder.of(libPath).findAll().stream()\n    .map(m -> m.descriptor().name()).filter(n -> n.startsWith(\"org.elasticsearch\")).sorted().toList();\nList<String> missing = new ArrayList<>(EXPECTED_ES_SERVER_MODULES); missing.removeAll(actual);\nList<String> extra = new ArrayList<>(actual); extra.removeAll(EXPECTED_ES_SERVER_MODULES);\nif (missing.isEmpty() == false || extra.isEmpty() == false) {\n    System.err.println(\"Module mismatch — missing: \" + missing + \", extra: \" + extra);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["distribution","modules","jpms","manifest","validation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}