hashicorp/packer · error
hash %q: %w
Error message
hash %q: %w
What it means
While deriving subjects, each file listed by artifact.Files() is hashed with sha256File, which opens the file and copies it into a SHA-256 hasher. If opening or reading a file fails, deriveSubjects wraps the underlying error as `hash %q: %w` naming the file. This means an artifact advertised a file that is missing, unreadable, or failed mid-read.
Source
Thrown at internal/provenance/subject.go:45
return deriveSubjects(artifact)
}
func DeriveIdentityRecord(artifact packersdk.Artifact) (map[string]interface{}, error) {
return deriveIdentityRecord(artifact)
}
func deriveSubjects(artifact packersdk.Artifact) ([]Subject, error) {
if artifact == nil {
return nil, fmt.Errorf("artifact is nil")
}
files := artifact.Files()
if len(files) > 0 {
subjects := make([]Subject, 0, len(files))
for _, file := range files {
digest, err := sha256File(file)
if err != nil {
return nil, fmt.Errorf("hash %q: %w", file, err)
}
subjects = append(subjects, Subject{
Name: filepath.Base(file),
Digest: DigestSet{
"sha256": digest,
},
})
}
return subjects, nil
}
identity, err := deriveIdentityRecord(artifact)
if err != nil {
return nil, err
}
View on GitHub (pinned to eb36e3c3e4)
Solutions
- Inspect the wrapped cause (%w) to distinguish os.Open 'no such file or directory' vs 'permission denied' vs read error
- Verify the file path exists and is readable: ls -l / stat the path from the error message
- Re-run the build so the artifact files are regenerated consistently
- Check the builder plugin's Files() implementation for stale or incorrect paths
- Run with sufficient privileges if the artifact lives in a protected location
Example fix
// before
subjects, err := provenance.DeriveSubjects(artifact)
if err != nil { return err }
// after
subjects, err := provenance.DeriveSubjects(artifact)
if err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && os.IsNotExist(pe) {
log.Warnf("skipping provenance, artifact file missing: %v", err)
return nil
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
for _, f := range artifact.Files() {
if _, err := os.Stat(f); err != nil {
return fmt.Errorf("artifact file unavailable before hashing: %w", err)
}
} Try / catch
subjects, err := provenance.DeriveSubjects(artifact)
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) { return fmt.Errorf("cannot hash artifact file %s: %w", perr.Path, perr.Err) }
return err
} Prevention
- Ensure artifact files remain on disk for the packer process lifetime
- Run with read permissions on builder output directories
- Avoid deleting/moving artifact files between build and post-processing
When it happens
Trigger: artifact.Files() returns a path that does not exist on disk; the file exists but lacks read permission; the file is a dangling symlink; an I/O error occurs while reading; file was deleted between Files() and hashing.
Common situations: Docker/docker export artifacts referencing removed temp files; artifacts built on a different host or container layer; running packer as a non-root user without access to builder output; NFS/overlay filesystem issues during long builds.
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
- failed to open %s for hashing: %w
- read verifier %q: %w
- read signer %q: %w
- open artifact %q for bundle verification: %w
- artifact is nil
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/97d6ef571fdd62f1.
Report an issue: GitHub.