{"record":{"id":"6d33f9bd81ded94e","repo":"kubernetes/kops","slug":"error-opening-file-q-v-6d33f9","errorCode":null,"errorMessage":"error opening file %q: %v","messagePattern":"error opening file %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/hashing/hash.go","lineNumber":143,"sourceCode":"\treturn ha.FromString(s)\n}\n\nfunc (ha HashAlgorithm) Hash(r io.Reader) (*Hash, error) {\n\thasher := ha.NewHasher()\n\t_, err := copyToHasher(hasher, r)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error while hashing resource: %v\", err)\n\t}\n\treturn &Hash{Algorithm: ha, HashValue: hasher.Sum(nil)}, nil\n}\n\nfunc (ha HashAlgorithm) HashFile(p string) (*Hash, error) {\n\tf, err := os.OpenFile(p, os.O_RDONLY, 0)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, fmt.Errorf(\"error opening file %q: %v\", p, err)\n\t}\n\tdefer try.CloseFile(f)\n\treturn ha.Hash(f)\n}\n\nfunc copyToHasher(dest io.Writer, src io.Reader) (int64, error) {\n\tn, err := io.Copy(dest, src)\n\tif err != nil {\n\t\treturn n, fmt.Errorf(\"error hashing data: %v\", err)\n\t}\n\treturn n, nil\n}\n\nfunc (l *Hash) Equal(r *Hash) bool {\n\treturn (l.Algorithm == r.Algorithm) && bytes.Equal(l.HashValue, r.HashValue)\n}\n","sourceCodeStart":125,"sourceCodeEnd":160,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/hashing/hash.go#L125-L160","documentation":"HashAlgorithm.HashFile opens the file at path p read-only before hashing. If os.OpenFile fails with an error other than not-exist (permission denied, path is a directory, I/O error), it is wrapped in this error. Note: a genuinely missing file returns the raw os.ErrNotExist without this wrapper.","triggerScenarios":"Calling HashAlgorithm.HashFile(\"/path/to/file\") where the path exists but is unreadable (wrong permissions), is a directory, or the device returns an I/O error; also via fileHasHash / Hash call sites.","commonSituations":"Running kops as a non-root user against root-owned node files; pointing hash verification at a directory instead of a file; NFS/readonly-mount failures; SELinux denials.","solutions":["Check the file exists and is a regular file, and that the current user has read permission (ls -l)","Fix permissions (chmod/chown) or run the command as a user with access","If the file may legitimately be absent, handle os.IsNotExist first — it is returned unwrapped"],"exampleFix":"// before\nh, err := algo.HashFile(dirPath) // dirPath is a directory\n// after\nfi, err := os.Stat(dirPath)\nif err != nil { return err }\nif fi.IsDir() { return fmt.Errorf(\"%s is a directory\", dirPath) }\nh, err := algo.HashFile(dirPath)","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(p)\nif err != nil { return err }\nif fi.IsDir() { return fmt.Errorf(\"%s is a directory, not a file\", p) }\nif f, err := os.Open(p); err != nil {\n\treturn fmt.Errorf(\"no read permission for %s: %w\", p, err)\n} else { f.Close() }","typeGuard":"null","tryCatchPattern":"h, err := algo.HashFile(p)\nif err != nil {\n\tif os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"file %s not found; re-download or fix path\", p)\n\t}\n\treturn fmt.Errorf(\"cannot open %s for hashing: %w\", p, err)\n}","preventionTips":["Stat the path and confirm it is a regular, readable file before hashing","Run with sufficient privileges for root-owned files","Distinguish os.IsNotExist (returned unwrapped) from other open errors","Avoid pointing verification at directories or symlink loops"],"tags":["hashing","filesystem","permissions"],"backgroundTag":"file-open-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}