{"record":{"id":"4c9c60a1fe0402b7","repo":"elastic/elasticsearch","slug":"name-found-in-top-level-directory-unnamed-packa","errorCode":null,"errorMessage":"{name} found in top-level directory (unnamed package not allowed in module)","messagePattern":"(.+?) found in top-level directory \\(unnamed package not allowed in module\\)","errorType":"exception","errorClass":"InvalidModuleDescriptorException","httpStatus":null,"severity":"error","filePath":"libs/core/src/main/java/org/elasticsearch/core/internal/provider/EmbeddedModulePath.java","lineNumber":218,"sourceCode":"\n    // Drops comments and trims the given string.\n    private static String dropCommentAndTrim(String line) {\n        int ci = line.indexOf('#');\n        if (ci >= 0) {\n            line = line.substring(0, ci);\n        }\n        return line.trim();\n    }\n\n    // Returns an optional containing the package name from a given path and separator, or an\n    // empty optional if none.\n    static Optional<String> toPackageName(Path file, String separator) {\n        Path parent = file.getParent();\n        if (parent == null) {\n            String name = file.toString();\n            if (name.endsWith(\".class\") && name.equals(MODULE_INFO) == false) {\n                String msg = name + \" found in top-level directory (unnamed package not allowed in module)\";\n                throw new InvalidModuleDescriptorException(msg);\n            }\n            return Optional.empty();\n        }\n\n        String pn = parent.toString().replace(separator, \".\");\n        if (isPackageName(pn)) {\n            return Optional.of(pn);\n        } else {\n            // not a valid package name\n            return Optional.empty();\n        }\n    }\n\n    // Returns an optional containing the package name from a given binary class path name, or an\n    // empty optional if none.\n    static Optional<String> toPackageName(String name, String separator) {\n        assert name.endsWith(separator) == false;\n        int index = name.lastIndexOf(separator);","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/core/src/main/java/org/elasticsearch/core/internal/provider/EmbeddedModulePath.java#L200-L236","documentation":"Thrown as an InvalidModuleDescriptorException by EmbeddedModulePath.toPackageName(Path, String) when a .class file (other than module-info.class) is found at the top-level directory of a module's jar — i.e. it has no parent directory and thus belongs to the unnamed package. The Java Platform explicitly forbids the unnamed package in modules, so this is a fatal descriptor error during automatic-module scanning.","triggerScenarios":"An embedded jar that will become a module contains a top-level .class file (e.g. 'Foo.class' at the jar root, not under any package directory) other than module-info.class. The scan hits toPackageName, parent is null, and the check at line 216 fires.","commonSituations":"Shading classes into a jar without preserving package directories. A compiled class whose package declaration was removed/empty (legacy code in the default package). Bundling a script-generated .class at the root. A bad zip/jar assembly step that flattens directories.","solutions":["Move the offending .class file into a directory matching its package declaration; never place classes at the jar root.","If the class genuinely has no package, delete it or rewrite it to declare a package before packaging.","Rebuild the jar with proper structure (Gradle/Maven jar tasks preserve package dirs by default — investigate any custom shading).","Inspect the jar: `jar tf x.jar | grep -E '^[^/]+\\.class$'` to find top-level class files."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-scan a jar for top-level class files before module-mode loading\nboolean hasNoTopLevelClasses(Path jar) throws IOException {\n    try (JarFile j = new JarFile(jar.toFile())) {\n        return j.stream().noneMatch(e -> e.getName().endsWith(\".class\")\n            && !e.getName().equals(\"module-info.class\")\n            && !e.getName().contains(\"/\"));\n    }\n}","typeGuard":"static boolean isModuleSafeJar(Path jar) throws IOException {\n    try (JarFile j = new JarFile(jar.toFile())) {\n        return j.stream().filter(e -> e.getName().endsWith(\".class\")).allMatch(e -> e.getName().contains(\"/\") || e.getName().equals(\"module-info.class\"));\n    }\n}","tryCatchPattern":"try {\n    return EmbeddedModulePath.descriptorFor(path);\n} catch (InvalidModuleDescriptorException e) {\n    if (e.getMessage().contains(\"top-level directory\")) {\n        // repack the jar with proper package directories; identify the entry via the message\n        throw new RuntimeException(\"jar has unnamed-package class: \" + path, e);\n    }\n    throw e;\n}","preventionTips":["Never place .class files at the jar root; always under their package directory.","Every compiled class must declare a package.","Inspect jars with `jar tf x.jar | grep -E '^[^/]+\\.class$'` before embedding.","Investigate shading steps that may flatten directory structures."],"tags":["modules","jpms","packaging","class-file","provider","elasticsearch-core"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}