{"record":{"id":"69e872331b8da567","repo":"twpayne/chezmoi","slug":"s-parse-error","errorCode":null,"errorMessage":"%s: parse error","messagePattern":"(.+?): parse error","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/data.go","lineNumber":91,"sourceCode":"func maybeUnquote(s string) string {\n\tif unquotedS, err := unquote(s); err == nil {\n\t\treturn unquotedS\n\t}\n\treturn s\n}\n\n// parseOSRelease parses operating system identification data from r as defined\n// by the os-release specification.\nfunc parseOSRelease(data []byte) (map[string]any, error) {\n\tresult := make(map[string]any)\n\tfor line := range bytes.Lines(data) {\n\t\ttoken := bytes.TrimSpace(line)\n\t\tif len(token) == 0 || token[0] == '#' {\n\t\t\tcontinue\n\t\t}\n\t\tkey, value, ok := bytes.Cut(token, []byte{'='})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"%s: parse error\", token)\n\t\t}\n\t\tresult[string(key)] = maybeUnquote(string(value))\n\t}\n\treturn result, nil\n}\n\nfunc unquote(s string) (string, error) {\n\tswitch {\n\tcase len(s) < 2:\n\t\tfallthrough\n\tcase s[0] != '\"' && s[0] != '\\'':\n\t\tfallthrough\n\tcase s[0] != s[len(s)-1]:\n\t\treturn \"\", strconv.ErrSyntax\n\tcase strings.IndexByte(s, '\\\\') == -1:\n\t\treturn s[1 : len(s)-1], nil\n\t}\n\tbs := []byte(s[1 : len(s)-1])","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/data.go#L73-L109","documentation":"parseOSRelease reads an /etc/os-release style file into a key/value map. Every non-comment, non-empty line must contain an '=' separating key and value; a line without '=' causes this error, reported with the offending line content. It signals a malformed or non-os-release file being parsed.","triggerScenarios":"Calling OSRelease (or the anonymous caller) on a file whose content has a line without 'key=value' form — e.g. a custom os-release override missing '=', stray prose, or CRLF/binary garbage.","commonSituations":"Pointing chezmoi at a wrong file for OS release detection, a customized /etc/os-release broken by manual edits, container images shipping a stub os-release with junk lines.","solutions":["Inspect the os-release file being parsed and fix the malformed line to key=value form","Restore the stock /etc/os-release from the distro package (e.g. reinstall the base-files/os-release package)","If a custom file is being fed in, correct or remove the offending line"],"exampleFix":"// before: broken os-release line\nNAME=\"Debian GNU/Linux\"\nDebian 12\n\n// after\nNAME=\"Debian GNU/Linux\"\nVERSION=\"12 (bookworm)\"","handlingStrategy":"validation","validationCode":"for i, line := range bytes.Split(data, []byte{'\\n'}) {\n    line = bytes.TrimSpace(line)\n    if len(line) == 0 || line[0] == '#' { continue }\n    if !bytes.Contains(line, []byte{'='}) {\n        return fmt.Errorf(\"line %d has no '=': %q\", i+1, line)\n    }\n}","typeGuard":null,"tryCatchPattern":"osRelease, err := OSRelease()\nif err != nil && strings.HasSuffix(err.Error(), \"parse error\") {\n    // treat as unknown OS / use fallback detection\n}","preventionTips":["Do not hand-edit /etc/os-release; use distro packages to manage it","Validate any custom os-release-like files are strict key=value","Strip CRLF and comments before parsing custom files"],"tags":["go","parsing","os-release","linux"],"backgroundTag":"parse-error","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}