elastic/elasticsearch · error · IOException

Support only file!: ${path}

Error message

Support only file!: ${path}

What it means

Thrown by ElasticsearchBuildCompletePlugin during CI-archive tar creation when a path in the file set is not a regular file (e.g. a directory, a special file, or a broken symlink). The archiver copies file contents into a tar.bz2 stream and only handles regular files.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchBuildCompletePlugin.java:303

        }

        private static void createBuildArchiveTar(List<File> files, File projectDir, File uploadFile) {
            try (
                OutputStream fOut = Files.newOutputStream(uploadFile.toPath());
                BufferedOutputStream buffOut = new BufferedOutputStream(fOut);
                BZip2CompressorOutputStream bzOut = new BZip2CompressorOutputStream(buffOut);
                TarArchiveOutputStream tOut = new TarArchiveOutputStream(bzOut)
            ) {
                Path projectPath = projectDir.toPath();
                tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
                tOut.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
                for (Path path : files.stream().map(File::toPath).toList()) {
                    if (Files.exists(path) == false) {
                        log.warn("File disappeared before it could be added to CI archive: " + path);
                        continue;
                    } else if (!Files.isRegularFile(path)) {
                        throw new IOException("Support only file!: " + path);
                    }

                    long entrySize = Files.size(path);
                    TarArchiveEntry tarEntry = new TarArchiveEntry(path.toFile(), calculateArchivePath(path, projectPath));
                    tarEntry.setSize(entrySize);
                    tOut.putArchiveEntry(tarEntry);

                    // copy file to TarArchiveOutputStream
                    try (BufferedInputStream bin = new BufferedInputStream(Files.newInputStream(path))) {
                        IOUtils.copyLarge(bin, tOut, 0, entrySize);
                    }
                    tOut.closeArchiveEntry();

                }
                tOut.flush();
                tOut.finish();

            } catch (IOException e) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Filter the input set so only regular files are passed to the archiver (Files.isRegularFile check at configuration time).
  2. Resolve symlinks before archiving or exclude them.
  3. Verify each configured path points at a file, not a directory.
  4. Handle the 'file disappeared' log warning to distinguish deletion vs non-regular cases.

Example fix

// before
for (Path path : files.stream().map(File::toPath).toList()) { /* archiver errors on dirs */ }
// after
List<Path> regularOnly = files.stream().map(File::toPath).filter(Files::isRegularFile).toList();
Defensive patterns

Strategy: validation

Validate before calling

List<Path> regularOnly = files.stream()
    .map(File::toPath)
    .filter(p -> Files.exists(p) && Files.isRegularFile(p))
    .toList();
if (regularOnly.size() != files.size()) {
    log.warn("Some archive inputs were not regular files and were skipped");
}

Try / catch

try {
    if (!Files.isRegularFile(path)) throw new IOException("Support only file!: " + path);
} catch (IOException e) {
    log.warn("Skipping non-regular archive input: " + path, e);
}

Prevention

When it happens

Trigger: A configured archive input resolves to a directory or non-regular file, or a file was replaced by a directory/symlink between enumeration and the Files.isRegularFile check.

Common situations: An archive glob accidentally matched a directory; a symlink target is missing; a generated artifact path changed shape between configuration and execution.

Related errors


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