{"record":{"id":"69027456db9cbd3a","repo":"git-ecosystem/git-credential-manager","slug":"missing-section-header","errorCode":null,"errorMessage":"Missing section header","messagePattern":"Missing section header","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Core/IniFile.cs","lineNumber":171,"sourceCode":"                        continue;\n                    }\n\n                    if (!iniFile.TryGetSection(mainName, subName, out section))\n                    {\n                        var sectionName = new IniSectionName(mainName, subName);\n                        section = new IniSection(sectionName);\n                        iniFile.Sections[sectionName] = section;\n                    }\n\n                    continue;\n                }\n\n                match = PropertyRegex.Match(line);\n                if (match.Success)\n                {\n                    if (section is null)\n                    {\n                        throw new Exception(\"Missing section header\");\n                    }\n\n                    string propName = match.Groups[\"name\"].Value;\n                    string propValue = match.Groups[\"value\"].Value.Trim();\n\n                    // Trim trailing comments\n                    int firstDQuote = propValue.IndexOf('\"');\n                    int lastDQuote = propValue.LastIndexOf('\"');\n                    int commentIdx = propValue.LastIndexOf('#');\n                    if (commentIdx > -1)\n                    {\n                        bool insideDQuotes = firstDQuote > -1 && lastDQuote > -1 &&\n                                             (firstDQuote < commentIdx && commentIdx < lastDQuote);\n\n                        if (!insideDQuotes)\n                        {\n                            propValue = propValue.Substring(0, commentIdx).Trim();\n                        }","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/IniFile.cs#L153-L189","documentation":"IniFile.Deserialize parses .gitconfig-style INI content line by line; if a property line (key = value) appears before any [section] header has been seen, 'section' is still null and the parser throws \"Missing section header\". INI format requires properties to belong to a section, so a leading bare property is unrepresentable.","triggerScenarios":"Deserializing config text/file where a property line occurs before the first [section] line — e.g. a file starting with \"name = value\", corrupted config missing its first header, or a truncated file.","commonSituations":"Hand-edited or machine-generated .gitconfig files missing the initial [core]/[user] header, config files concatenated incorrectly, or templates where the section header line was deleted.","solutions":["Open the config file and ensure every property appears under a [section] header — add the missing header at the top","Check the exact line the parser failed on (it is the first property line before any section)","Regenerate the config from a known-good template rather than hand-editing","If constructing INI text programmatically, always emit \"[section]\\n\" before any key=value pairs"],"exampleFix":"// before (file content)\n// name = value\n//\n// after\n// [user]\n// name = value","handlingStrategy":"try-catch","validationCode":"var text = File.ReadAllText(path);\nvar firstNonEmpty = text.Split('\\n').FirstOrDefault(l => !string.IsNullOrWhiteSpace(l)) ?? \"\";\nif (!firstNonEmpty.TrimStart().StartsWith(\"[\"))\n    throw new InvalidDataException($\"{path}: first content line must be a [section] header\");","typeGuard":"bool HasSectionHeader(string iniText) => iniText\n    .Split('\\n')\n    .Any(l => l.TrimStart().StartsWith(\"[\")) &&\n    !string.IsNullOrWhiteSpace(iniText.Split('\\n').FirstOrDefault(l => !string.IsNullOrWhiteSpace(l))) &&\n    iniText.Split('\\n').First(l => !string.IsNullOrWhiteSpace(l)).TrimStart().StartsWith(\"[\");","tryCatchPattern":"try\n{\n    var ini = IniFile.Deserialize(path, fileSystem);\n}\ncatch (Exception ex) when (ex.Message == \"Missing section header\")\n{\n    logger.LogError(ex, \"{Path} is malformed: a key=value appears before any [section] header\", path);\n}","preventionTips":["Never hand-edit git config files without preserving [section] headers","Validate config files parse (round-trip via IniFile) after automated edits","When generating INI text, always emit the section header before key=value lines"],"tags":["ini","config-parsing","gitconfig","malformed-input"],"backgroundTag":"schema-validation-failed","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}