{"record":{"id":"97d6ef571fdd62f1","repo":"hashicorp/packer","slug":"hash-q-w","errorCode":null,"errorMessage":"hash %q: %w","messagePattern":"hash %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/provenance/subject.go","lineNumber":45,"sourceCode":"\treturn deriveSubjects(artifact)\n}\n\nfunc DeriveIdentityRecord(artifact packersdk.Artifact) (map[string]interface{}, error) {\n\treturn deriveIdentityRecord(artifact)\n}\n\nfunc deriveSubjects(artifact packersdk.Artifact) ([]Subject, error) {\n\tif artifact == nil {\n\t\treturn nil, fmt.Errorf(\"artifact is nil\")\n\t}\n\n\tfiles := artifact.Files()\n\tif len(files) > 0 {\n\t\tsubjects := make([]Subject, 0, len(files))\n\t\tfor _, file := range files {\n\t\t\tdigest, err := sha256File(file)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"hash %q: %w\", file, err)\n\t\t\t}\n\n\t\t\tsubjects = append(subjects, Subject{\n\t\t\t\tName: filepath.Base(file),\n\t\t\t\tDigest: DigestSet{\n\t\t\t\t\t\"sha256\": digest,\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\n\t\treturn subjects, nil\n\t}\n\n\tidentity, err := deriveIdentityRecord(artifact)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/provenance/subject.go#L27-L63","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nsubjects, err := provenance.DeriveSubjects(artifact)\nif err != nil { return err }\n// after\nsubjects, err := provenance.DeriveSubjects(artifact)\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && os.IsNotExist(pe) {\n        log.Warnf(\"skipping provenance, artifact file missing: %v\", err)\n        return nil\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"for _, f := range artifact.Files() {\n    if _, err := os.Stat(f); err != nil {\n        return fmt.Errorf(\"artifact file unavailable before hashing: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"subjects, err := provenance.DeriveSubjects(artifact)\nif err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) { return fmt.Errorf(\"cannot hash artifact file %s: %w\", perr.Path, perr.Err) }\n    return err\n}","preventionTips":["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"],"tags":["go","file-io","sha256","artifact"],"backgroundTag":"file-read-failed","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}