elastic/elasticsearch · error · GradleException

failed writing tar file [${tarFile}]

Error message

failed writing tar file [${tarFile}]

What it means

Thrown by SymbolicLinkPreservingTar's copy action when an IOException escapes the top-level try-with-resources that opens and writes the tar archive output stream. This wraps failures in creating/closing the compressed stream (gzip/bzip2/uncompressed) or any unhandled error during stream.process(...). It is the outer guard; per-entry failures are reported separately by error 178.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/SymbolicLinkPreservingTar.java:81

            final Provider<RegularFile> tarFile,
            final ArchiveOutputStreamFactory compressor,
            final boolean isPreserveFileTimestamps
        ) {
            this.tarFile = tarFile;
            this.compressor = compressor;
            this.isPreserveFileTimestamps = isPreserveFileTimestamps;
        }

        @Override
        public WorkResult execute(final CopyActionProcessingStream stream) {
            try (
                OutputStream out = compressor.createArchiveOutputStream(tarFile.get().getAsFile());
                TarArchiveOutputStream tar = new TarArchiveOutputStream(out)
            ) {
                tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
                stream.process(new SymbolicLinkPreservingTarStreamAction(tar));
            } catch (final IOException e) {
                throw new GradleException("failed writing tar file [" + tarFile + "]", e);
            }

            return WorkResults.didWork(true);
        }

        private class SymbolicLinkPreservingTarStreamAction implements CopyActionProcessingStreamAction {

            private final TarArchiveOutputStream tar;

            /*
             * When Gradle walks the file tree, it will follow symbolic links. This means that if there is a symbolic link to a directory
             * in the source file tree, we could otherwise end up duplicating the entries below that directory in the resulting tar archive.
             * To avoid this, we track which symbolic links we have visited, and skip files that are children of symbolic links that we have
             * already visited.
             */
            private final Set<File> visitedSymbolicLinks = new HashSet<>();

            SymbolicLinkPreservingTarStreamAction(final TarArchiveOutputStream tar) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Check the archiveFile target path (shown as tarFile in the message): ensure its parent directory exists and is writable.
  2. Free disk space on the target volume and retry.
  3. On Windows, ensure no other process (antivirus, explorer, archiver) holds the output file.
  4. Verify the task's compression setting matches a supported codec (GZIP/BZIP2/none).
  5. If the failure originates from a single entry, look for error 178 which carries the per-entry 'could not add' detail.
Defensive patterns

Strategy: try-catch

Validate before calling

import java.nio.file.*;
import java.io.File;
File target = archiveFile.getAsFile().get();
File parent = target.getParentFile();
if (parent == null || !parent.exists())
    throw new IllegalArgumentException("tar output parent missing: " + parent);
if (!parent.canWrite())
    throw new IllegalArgumentException("tar output dir not writable: " + parent);
if (target.exists() && !target.isFile())
    throw new IllegalArgumentException("tar target is not a regular file: " + target);
if (target.exists() && !target.canWrite())
    throw new IllegalArgumentException("existing tar target not writable: " + target);

Try / catch

try (OutputStream out = compressor.createArchiveOutputStream(tarFile.get().getAsFile());
     TarArchiveOutputStream tar = new TarArchiveOutputStream(out)) {
    tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
    stream.process(new SymbolicLinkPreservingTarStreamAction(tar));
} catch (final IOException e) {
    throw new GradleException("failed writing tar file [" + tarFile + "]", e);
}

Prevention

When it happens

Trigger: The execute(CopyActionProcessingStream) method opens compressor.createArchiveOutputStream(tarFile) and a TarArchiveOutputStream over it; any IOException during opening, writing headers via stream.process, or closing the streams is caught by catch (final IOException e) and rethrown.

Common situations: The archiveFile output path is not writable or its parent directory does not exist; disk full while writing the tar; the output file is locked by another process (Windows); permissions denied on the target directory; the compression codec threw during stream construction.

Related errors


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