hashicorp/packer · error

Unable to read file %s: %s

Error message

Unable to read file %s: %s

What it means

createTarArchive could not open one of the artifact files for reading while building the tar stream in Packer's compress post-processor. os.Open(path) failed for a specific path, so tar creation stops and PostProcess wraps the failure as 'Error creating tar'.

Source

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

}

func makePgzipWriter(output io.WriteCloser, compressionLevel int) (io.WriteCloser, error) {
	gzipWriter, err := pgzip.NewWriterLevel(output, compressionLevel)
	if err != nil {
		return nil, ErrInvalidCompressionLevel
	}
	_ = gzipWriter.SetConcurrency(500000, runtime.GOMAXPROCS(-1))
	return gzipWriter, nil
}

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

	for _, path := range files {
		file, err := os.Open(path)
		if err != nil {
			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)

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Check the failing path from the error: verify it exists and is readable (ls -l)
  2. Fix permissions or restore the missing file before the compress step
  3. Reorder post-processors so nothing deletes artifact files before compress runs
  4. Re-run the build from the builder step to regenerate the artifact files
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight: every artifact path must exist and be a readable regular file
for _, p := range artifact.Files() {
    fi, err := os.Stat(p)
    if err != nil { return fmt.Errorf("cannot tar %s: %w", p, err) }
    if !fi.Mode().IsRegular() { return fmt.Errorf("skipping non-regular file %s", p) }
    if file, err := os.Open(p); err != nil { return err } else { file.Close() }
}

Try / catch

// Go: unwrap to find the failing path
if err != nil && strings.Contains(err.Error(), "Error creating tar") {
    if strings.Contains(err.Error(), "Unable to read file") {
        // log path from inner message; restore permissions/file and retry
    }
    return err
}

Prevention

When it happens

Trigger: createTarArchive iterates artifact.Files() and os.Open returns an error for one path: file deleted after the artifact was produced, permission denied, or the path is a dangling symlink/directory.

Common situations: Artifact files removed between builder completion and the compress post-processor; running Packer without read permission on generated disk images; checksum/sidecar files referenced by the artifact no longer present.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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