elastic/elasticsearch · error · GradleException

Detected class file in distribution ('${file.getName()}')

Error message

Detected class file in distribution ('${file.getName()}')

What it means

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.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionArchiveCheckPlugin.java:213

            final List<String> actualLines = Files.readAllLines(path);
            int line = 0;
            for (final String expectedLine : expectedLines) {
                final String actualLine = actualLines.get(line);
                if (expectedLine.equals(actualLine) == false) {
                    throw new GradleException(
                        "expected line [" + (line + 1) + "] in [" + path + "] to be [" + expectedLine + "] but was [" + actualLine + "]"
                    );
                }
                line++;
            }
        } catch (IOException ioException) {
            throw new GradleException("Unable to read from file " + path, ioException);
        }
    }

    private static void assertNoClassFile(File file) {
        if (file.getName().endsWith(".class")) {
            throw new GradleException("Detected class file in distribution ('" + file.getName() + "')");
        }
    }

    private Object distTaskOutput(TaskProvider<Task> buildDistTask) {
        return new Callable<File>() {
            @Override
            public File call() {
                return buildDistTask.get().getOutputs().getFiles().getSingleFile();
            }

            @Override
            public String toString() {
                return call().getAbsolutePath();
            }
        };
    }

    private String calculateBuildTask(String projectName) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. 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).
  2. Ensure all compiled classes are packaged into JARs under lib/, not copied as loose files.
  3. If the .class is intentional (rare), reconsider the packaging — ES convention forbids loose class files.
  4. Run the distribution build with --info to see which task/stage copied the class file.

Example fix

// before: build.gradle copies compiled classes into distribution
from(sourceSets.main.output.classesDir)  // ships loose .class → throws

// after: package into a jar instead
from(jarTask)  // ships the jar, no loose class files
Defensive patterns

Strategy: validation

Validate before calling

if (file.getName().endsWith(".class")) {
    System.err.println("WARNING: loose class file detected: " + file);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/4cedb8e3923d2c99. Report an issue: GitHub.