hashicorp/packer · error

unable to compute %s hash for %s

Error message

unable to compute %s hash for %s

What it means

The checksum post-processor failed while copying the artifact file into the hash writer (io.Copy to hash.Hash). It wraps any read/compute failure into a single message naming the checksum type and the artifact path, so the original OS error is lost and must be inferred.

Source

Thrown at post-processor/checksum/post-processor.go:151

				newartifact.files = append(newartifact.files, checksumFile)
			}
			if err := os.MkdirAll(filepath.Dir(checksumFile), os.FileMode(0755)); err != nil {
				return nil, false, true, fmt.Errorf("unable to create dir: %s", err.Error())
			}
			fw, err := os.OpenFile(checksumFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0644))
			if err != nil {
				return nil, false, true, fmt.Errorf("unable to create file %s: %s", checksumFile, err.Error())
			}
			fr, err := os.Open(art)
			if err != nil {
				fw.Close()
				return nil, false, true, fmt.Errorf("unable to open file %s: %s", art, err.Error())
			}

			if _, err = io.Copy(h, fr); err != nil {
				fr.Close()
				fw.Close()
				return nil, false, true, fmt.Errorf("unable to compute %s hash for %s", ct, art)
			}
			fr.Close()
			_, _ = fw.WriteString(fmt.Sprintf("%x\t%s\n", h.Sum(nil), filepath.Base(art)))
			fw.Close()
			h.Reset()
		}
	}

	// sets keep and forceOverride to true because we don't want to accidentally
	// delete the very artifact we're checksumming.
	return newartifact, true, true, nil
}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Re-run packer to rule out a transient I/O error
  2. Verify the artifact file exists, is readable, and is not being mutated concurrently (chmod/ls -l, check no parallel post-processor deletes it)
  3. Check disk health/space (dmesg, df) on the output filesystem
  4. If on a network filesystem, copy the artifact locally before the checksum post-processor

Example fix

// before: original io error is swallowed
return nil, false, true, fmt.Errorf("unable to compute %s hash for %s", ct, art)
// after: preserve cause for diagnosis
return nil, false, true, fmt.Errorf("unable to compute %s hash for %s: %w", ct, art, err)
Defensive patterns

Strategy: try-catch

Validate before calling

stat, err := os.Stat(artifactPath)
if err != nil || !stat.Mode().IsRegular() {
    return fmt.Errorf("artifact not readable: %w", err)
}
// also ensure free disk space and no concurrent writers to the file

Try / catch

if err != nil {
    var pe *os.PathError
    if errors.As(err, &pe) {
        // inspect pe.Op/pe.Path to diagnose read failure
    }
    // retry once on transient I/O errors before failing the build
}

Prevention

When it happens

Trigger: io.Copy(h, fr) returns an error while hashing the artifact file in PostProcess — typically an I/O read failure (disk error, file truncated/removed between open and read, permissions changed mid-read) or a hash writer write panic-path failure.

Common situations: Running on a full or failing disk; artifact file deleted or shrunk by a later post-processor before checksum runs; network/shared filesystem (NFS/SMB) drop while reading a remotely stored artifact; SELinux/AppArmor denying reads.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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