{"record":{"id":"644d48e24bfb8731","repo":"hashicorp/nomad","slug":"failed-to-read-hash-file-s","errorCode":null,"errorMessage":"failed to read hash file %s","messagePattern":"failed to read hash file (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/resolvconf/lib.go","lineNumber":416,"sourceCode":"\t\t}\n\t}\n\n\treturn nil\n}\n\n// UserModified can be used to determine whether the resolv.conf file has been\n// modified since it was generated. It returns false with no error if the file\n// matches the hash, true with no error if the file no longer matches the hash,\n// and false with an error if the result cannot be determined.\nfunc UserModified(rcPath, rcHashPath string) (bool, error) {\n\tcurrRCHash, err := os.ReadFile(rcHashPath)\n\tif err != nil {\n\t\t// If the hash file doesn't exist, can only assume it hasn't been written\n\t\t// yet (so, the user hasn't modified the file it hashes).\n\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, errors.Wrapf(err, \"failed to read hash file %s\", rcHashPath)\n\t}\n\texpected, err := digest.Parse(string(currRCHash))\n\tif err != nil {\n\t\treturn false, errors.Wrapf(err, \"failed to parse hash file %s\", rcHashPath)\n\t}\n\tv := expected.Verifier()\n\tcurrRC, err := os.Open(rcPath)\n\tif err != nil {\n\t\treturn false, errors.Wrapf(err, \"failed to open %s to check for modifications\", rcPath)\n\t}\n\tdefer currRC.Close()\n\tif _, err := io.Copy(v, currRC); err != nil {\n\t\treturn false, errors.Wrapf(err, \"failed to hash %s to check for modifications\", rcPath)\n\t}\n\treturn !v.Verified(), nil\n}\n\nfunc (rc *ResolvConf) processLine(line string) {","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/resolvconf/lib.go#L398-L434","documentation":"This error is returned by ResolvConf.UserModified when reading the sidecar hash file (rcHashPath) that stores the digest of the resolv.conf contents fails with an error other than fs.ErrNotExist. The library hashes /etc/resolv.conf and persists the digest so it can later tell whether the file was modified outside the process. If the hash file cannot be read (permissions, I/O error), the modification state is unknowable, so the error is wrapped and returned instead of guessed.","triggerScenarios":"Calling ResolvConf.UserModified when the hash file exists but cannot be read: permission denied on the hash file path, an I/O error reading it, or the path being a directory/unreadable special file. A missing hash file returns (false, nil), not this error.","commonSituations":"Running in a container where the hash file was created by a different user (running the agent as non-root after an earlier run as root); read-only or full filesystem; state directory mounted with wrong ownership; security software blocking access to the file.","solutions":["Check and fix permissions/ownership of the hash file (rcHashPath) so the process user can read it: ls -l <rcHashPath>, then chmod/chown accordingly.","Verify the hash file path points to a regular readable file, not a directory or broken symlink; recreate it if corrupted.","Re-run the component as the same user that originally wrote the hash file, or delete the stale hash file so UserModified treats the file as unmodified.","Check filesystem health / disk errors (dmesg) if reads fail on otherwise valid files.","Regenerate the hash file via the library's Set path so the next UserModified call succeeds."],"exampleFix":"// before (hash file unreadable, running as non-root)\n// -rw------- root root /var/run/resolvconf.hash\n// UserModified() -> failed to read hash file ...\n\n// after\n// sudo chown appuser:appuser /var/run/resolvconf.hash\n// sudo chmod 600 /var/run/resolvconf.hash\n// UserModified() -> (false, nil)","handlingStrategy":"fallback","validationCode":"if h, err := os.Stat(rcHashPath); err != nil || h.IsDir() {\n\t// hash file unreadable: treat as unmodified or re-initialize state\n}","typeGuard":"func hashFileReadable(path string) bool {\n\tf, err := os.Open(path)\n\tif err != nil { return false }\n\tf.Close()\n\treturn true\n}","tryCatchPattern":"modified, err := rc.UserModified()\nif err != nil {\n\tif strings.Contains(err.Error(), \"failed to read hash file\") {\n\t\tlog.Warnf(\"hash file unreadable, assuming unmodified: %v\", err)\n\t\tmodified = false\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["Keep the process user consistent with whoever created the hash file (avoid mixing root/non-root runs).","Ensure the state directory has correct ownership and is writable before startup.","Recreate a stale or suspicious hash file instead of forcing reads of it.","Monitor filesystem health to catch read errors early."],"tags":["resolvconf","filesystem","permissions","dns"],"backgroundTag":"hash-file-read-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}