{"record":{"id":"e7f37d85b5257eb4","repo":"hashicorp/nomad","slug":"failed-to-parse-hash-file-s","errorCode":null,"errorMessage":"failed to parse hash file %s","messagePattern":"failed to parse hash file (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/resolvconf/lib.go","lineNumber":420,"sourceCode":"}\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) {\n\tfields := strings.Fields(line)\n\n\t// Strip blank lines and comments.\n\tif len(fields) == 0 || fields[0][0] == '#' || fields[0][0] == ';' {","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/resolvconf/lib.go#L402-L438","documentation":"This error is returned by ResolvConf.UserModified when the contents of the hash file cannot be parsed as a valid digest via digest.Parse. The hash file is expected to contain a valid digest string; if it is empty, truncated, or contains garbage, the stored expected hash cannot be reconstructed and the comparison against the live resolv.conf cannot proceed.","triggerScenarios":"Calling ResolvConf.UserModified when the hash file at rcHashPath exists and is readable but its contents are not a valid digest — e.g. an empty file, a partially written file from an interrupted Set, or a file overwritten by another tool.","commonSituations":"Crash or SIGKILL between file creation and full write of the hash; an init script or backup tool clobbering the hash file; manual editing of the state file; different library versions writing incompatible digest formats.","solutions":["Inspect the hash file contents (cat rcHashPath) — if empty or corrupt, delete it; the next Set/user flow will rewrite it and UserModified will report unmodified until then.","Ensure the code that writes the hash file writes it atomically (write to temp file then rename) to avoid truncated contents.","Check for concurrent writers to the same hash path (multiple processes/containers sharing the state dir) and isolate the path per instance.","Upgrade/align library versions so the digest format written matches the format parsed."],"exampleFix":"// before: corrupt/truncated hash file\n// cat /var/run/resolvconf.hash  ->  \"\" (empty)\n// UserModified() -> failed to parse hash file ...\n\n// after\n// rm /var/run/resolvconf.hash   // regenerate via library Set\n// UserModified() -> (false, nil)","handlingStrategy":"validation","validationCode":"data, err := os.ReadFile(rcHashPath)\nif err != nil { return err }\nif len(data) == 0 {\n\t// invalid digest: delete file so library regenerates it\n\tos.Remove(rcHashPath)\n}","typeGuard":"func hashFileNonEmpty(path string) bool {\n\tfi, err := os.Stat(path)\n\treturn err == nil && fi.Mode().IsRegular() && fi.Size() > 0\n}","tryCatchPattern":"modified, err := rc.UserModified()\nif err != nil && strings.Contains(err.Error(), \"failed to parse hash file\") {\n\tos.Remove(rcHashPath) // regenerate on next write\n\tmodified = false\n}","preventionTips":["Write the hash file atomically (temp file + rename) to avoid truncated contents.","Never hand-edit or redirect other output into the hash file.","Avoid multiple processes sharing the same hash path.","Pin library versions so digest formats stay compatible."],"tags":["resolvconf","digest","corruption","parsing"],"backgroundTag":"invalid-digest-format","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"}