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
- Check free disk space and permissions on the output artifact path; a full/broken output stream is the most common root cause.
- Re-run the build; transient stream/pipe failures disappear on retry once the environment is healthy.
- Inspect the wrapped cause (%s at the end) — it names the real tar/compression writer error.
- 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
- Keep compress output on a volume with free space >= artifact size.
- Check `df -h` before large builds in CI.
- Don't point output at pipes or flaky network mounts.
- Read the wrapped cause in the error for the real writer failure.
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
- Failed to copy %s data to archive: %s
- Error creating tar: %s
- Failed to create tar header for %s: %s
- Failed to add zip header for %s: %s
- extract file: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/19725c7e1ed2226b.
Report an issue: GitHub.