hashicorp/packer · error

Failed to write tar header for %s: %s

Error message

Failed to write tar header for %s: %s

What it means

The compress post-processor's createTarArchive writes each file into the tar stream: it first writes the tar header via archive.WriteHeader(header). When the underlying archive/tar writer reports a write failure (or invalid header), the post-processor wraps it in this error with the file path and cause. The archive build aborts and the post-processor fails.

Source

Thrown at post-processor/compress/post-processor.go:402

			return fmt.Errorf("Unable to read file %s: %s", path, err)
		}
		defer file.Close()

		fi, err := file.Stat()
		if err != nil {
			return fmt.Errorf("Unable to get fileinfo for %s: %s", path, err)
		}

		header, err := tar.FileInfoHeader(fi, path)
		if err != nil {
			return fmt.Errorf("Failed to create tar header for %s: %s", path, err)
		}

		// workaround for archive format on go >=1.10
		setHeaderFormat(header)

		if err := archive.WriteHeader(header); err != nil {
			return fmt.Errorf("Failed to write tar header for %s: %s", path, err)
		}

		if _, err := io.Copy(archive, file); err != nil {
			return fmt.Errorf("Failed to copy %s data to archive: %s", path, err)
		}
	}
	return nil
}

func createZipArchive(files []string, output io.WriteCloser) error {
	archive := zip.NewWriter(output)
	defer archive.Close()

	for _, path := range files {
		path = filepath.ToSlash(path)

		source, err := os.Open(path)
		if err != nil {

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Check free disk space and permissions on the output artifact path; a full/broken output stream is the most common root cause.
  2. Re-run the build; transient stream/pipe failures disappear on retry once the environment is healthy.
  3. Inspect the wrapped cause (%s at the end) — it names the real tar/compression writer error.
  4. If the file path is special (device node, very long name), archive it via a format/level that supports it, or exclude it from the artifact.

Example fix

// before
"post-processors": [[{"type": "compress", "output": "/mnt/ro/artifact.tar.gz"}]]
// after (writable output path)
"post-processors": [[{"type": "compress", "output": "output/artifact.tar.gz"}]]
Defensive patterns

Strategy: validation

Validate before calling

// preflight: ensure output location is writable and has space
const output = "output/artifact.tar.gz"
if fs.statSync(path.dirname(output)).sizeHintCheck === false { /* abort */ }
fs.accessSync(path.dirname(output), fs.constants.W_OK)

Try / catch

// shell: fail fast and surface wrapped cause
packer build template.pkr.hcl || { df -h .; exit 1; }

Prevention

When it happens

Trigger: tar.Writer.WriteHeader returns an error — typically because the writer's underlying pipe/compression stream is broken or closed, the header is invalid (e.g. unsupported typeflag for the format), or the previous io.Copy left the writer in an error state.

Common situations: Disk full or output stream broken mid-archive; compression writer (gzip/etc.) already failed and the error surfaced on the next header write; extremely large files pushing header fields (size) beyond the selected tar format limits; running on go <1.10 where setHeaderFormat behavior differs.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/19725c7e1ed2226b. Report an issue: GitHub.