{"record":{"id":"a14b06553c62d61f","repo":"OpenNHP/opennhp","slug":"failed-to-open-file-w","errorCode":null,"errorMessage":"failed to open file: %w","messagePattern":"failed to open file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/utils/crypto.go","lineNumber":136,"sourceCode":"\treturn base64.StdEncoding.EncodeToString(pivKey), base64.StdEncoding.EncodeToString(pubKey)\n}\n\n// Md5sum computes MD5 checksum for file integrity verification (not cryptographic security)\n//\n//nolint:gosec // G401: MD5 used for file integrity checksums, not for cryptographic security\nfunc Md5sum(fullFilePath string) (string, error) {\n\tfileInfo, err := os.Stat(fullFilePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"file not found: %w\", err)\n\t}\n\n\tif !fileInfo.Mode().IsRegular() {\n\t\treturn \"\", fmt.Errorf(\"path is not a regular file\")\n\t}\n\n\tfile, err := os.Open(fullFilePath) //nolint:gosec // G304: Path validated by os.Stat above\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to open file: %w\", err)\n\t}\n\tdefer file.Close()\n\n\thasher := md5.New()\n\n\tif _, err := io.Copy(hasher, file); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to read file content: %w\", err)\n\t}\n\n\t// Convert hash to hex string\n\treturn hex.EncodeToString(hasher.Sum(nil)), nil\n}\n","sourceCodeStart":118,"sourceCodeEnd":149,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/utils/crypto.go#L118-L149","documentation":"Md5sum opens the (already stat-validated) file with os.Open; if the open syscall fails despite the successful Stat — typically due to a permission race, an unreadable symlink target, or too many open files — the underlying error is wrapped as \"failed to open file: %w\". This is distinct from the not-found and not-regular-file checks that run first.","triggerScenarios":"os.Stat succeeds but os.Open fails: the file was removed between Stat and Open; the file's permission bits deny read access to the process user; the fd limit (ulimit -n) is exhausted; the file is on a failing mount.","commonSituations":"Running the daemon as a non-root user while the TA/plugin file is root-only (0600 root:root); NFS/FUSE mount dropped between checks; very high fd usage in a long-running process hitting EMFILE.","solutions":["Check file permissions (ls -l) and grant read access to the process user, e.g. chmod o+r or chown to the service user","Re-check the fd limit (ulimit -n / systemd LimitNOFILE) and raise it if EMFILE appears in the wrapped error","Confirm the file still exists at the exact moment of the call (race between Stat and Open implies concurrent deletion — stabilize the deployment)","Inspect the wrapped inner error (%w) to distinguish EACCES from EMFILE or EIO"],"exampleFix":"// before (deployment)\n-rw------- root root /opt/nhp/ta.so\n// after\nchown nhp:nhp /opt/nhp/ta.so && chmod 0400 /opt/nhp/ta.so","handlingStrategy":"validation","validationCode":"f, err := os.Open(p); if err != nil { return err }; f.Close()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure service-user read permissions on deployed artifacts"],"tags":["go","filesystem","permissions","file"],"backgroundTag":"file-open-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}