{"record":{"id":"4cedb8e3923d2c99","repo":"elastic/elasticsearch","slug":"detected-class-file-in-distribution-file-getna","errorCode":null,"errorMessage":"Detected class file in distribution ('${file.getName()}')","messagePattern":"Detected class file in distribution \\('(.+?)'\\)","errorType":"validation","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionArchiveCheckPlugin.java","lineNumber":213,"sourceCode":"            final List<String> actualLines = Files.readAllLines(path);\n            int line = 0;\n            for (final String expectedLine : expectedLines) {\n                final String actualLine = actualLines.get(line);\n                if (expectedLine.equals(actualLine) == false) {\n                    throw new GradleException(\n                        \"expected line [\" + (line + 1) + \"] in [\" + path + \"] to be [\" + expectedLine + \"] but was [\" + actualLine + \"]\"\n                    );\n                }\n                line++;\n            }\n        } catch (IOException ioException) {\n            throw new GradleException(\"Unable to read from file \" + path, ioException);\n        }\n    }\n\n    private static void assertNoClassFile(File file) {\n        if (file.getName().endsWith(\".class\")) {\n            throw new GradleException(\"Detected class file in distribution ('\" + file.getName() + \"')\");\n        }\n    }\n\n    private Object distTaskOutput(TaskProvider<Task> buildDistTask) {\n        return new Callable<File>() {\n            @Override\n            public File call() {\n                return buildDistTask.get().getOutputs().getFiles().getSingleFile();\n            }\n\n            @Override\n            public String toString() {\n                return call().getAbsolutePath();\n            }\n        };\n    }\n\n    private String calculateBuildTask(String projectName) {","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionArchiveCheckPlugin.java#L195-L231","documentation":"Thrown as GradleException by assertNoClassFile() when a file ending in '.class' is encountered during archive extraction. The checkExtraction Copy task registers an eachFile callback (line 189) that rejects any .class file in the distribution — ES distributions should ship JARs, not loose class files, so a loose .class indicates a packaging bug.","triggerScenarios":"registerCheckExtractionTask wires eachFile(fileCopyDetails -> assertNoClassFile(fileCopyDetails.getFile())) at line 189. For every file copied from the tar/zip archive, if file.getName().endsWith(\".class\"), the GradleException is thrown, failing the Copy task during extraction.","commonSituations":"A build script accidentally copies compiled classes into a distribution directory instead of into a JAR; a plugin adds a class file to a config/ or bin/ directory; a dependency unzips classes into the distribution staging area; refactoring moved a class file resource into a packaged dir.","solutions":["Identify the offending .class file from the error message and trace where it enters the distribution (grep the distribution build scripts for the source path).","Ensure all compiled classes are packaged into JARs under lib/, not copied as loose files.","If the .class is intentional (rare), reconsider the packaging — ES convention forbids loose class files.","Run the distribution build with --info to see which task/stage copied the class file."],"exampleFix":"// before: build.gradle copies compiled classes into distribution\nfrom(sourceSets.main.output.classesDir)  // ships loose .class → throws\n\n// after: package into a jar instead\nfrom(jarTask)  // ships the jar, no loose class files","handlingStrategy":"validation","validationCode":"if (file.getName().endsWith(\".class\")) {\n    System.err.println(\"WARNING: loose class file detected: \" + file);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never copy compiled classes directly into distribution staging — package into JARs.","Review distribution build scripts for 'from(sourceSets.main.output)'.","Run checkExtraction locally after any packaging change.","Audit eachFile callbacks to catch stray class files early."],"tags":["distribution","packaging","validation","gradle"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}