{"record":{"id":"48d787ea6b099dc9","repo":"Humanizr/Humanizer","slug":"locale-yaml-root-must-be-a-mapping","errorCode":null,"errorMessage":"Locale YAML root must be a mapping.","messagePattern":"Locale YAML root must be a mapping\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs","lineNumber":1335,"sourceCode":"    {\n        sealed class LineInfo(int indent, string content, int lineNumber)\n        {\n            public int Indent { get; } = indent;\n            public string Content { get; } = content;\n            public int LineNumber { get; } = lineNumber;\n        }\n\n        public static SimpleYamlMapping Parse(string text)\n        {\n            var lines = NormalizeLines(text);\n            if (lines.Count == 0)\n            {\n                return new SimpleYamlMapping(ImmutableDictionary<string, SimpleYamlValue>.Empty.WithComparers(StringComparer.Ordinal));\n            }\n\n            var index = 0;\n            var value = ParseBlock(lines, ref index, 0, rejectDuplicateKeys: false);\n            return value is not SimpleYamlMapping mapping ? throw new InvalidOperationException(\"Locale YAML root must be a mapping.\") : mapping;\n        }\n\n        static List<LineInfo> NormalizeLines(string text)\n        {\n            var result = new List<LineInfo>();\n            var lines = text.Split([\"\\r\\n\", \"\\n\"], StringSplitOptions.None);\n\n            for (var lineNumber = 0; lineNumber < lines.Length; lineNumber++)\n            {\n                var rawLine = StripComment(lines[lineNumber]);\n                if (string.IsNullOrWhiteSpace(rawLine))\n                {\n                    continue;\n                }\n\n                var indent = 0;\n                while (indent < rawLine.Length && rawLine[indent] == ' ')\n                {","sourceCodeStart":1317,"sourceCodeEnd":1353,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs#L1317-L1353","documentation":"The locale YAML parser expects the document root to be a mapping (key-value pairs), because each locale file is a set of feature keys. If the top-level parsed node is a sequence or scalar — for instance the file starts with a list item — the root contract is violated and parsing aborts.","triggerScenarios":"A locale YAML file whose first non-blank, non-comment line begins with '- ' (a sequence item) or is a bare scalar, making the document root a sequence or scalar instead of a mapping.","commonSituations":"Accidentally prepending a list at the top of the file; truncating a file so only a fragment remains; pasting a YAML fragment that is a standalone list.","solutions":["Ensure the file's top level consists of 'key: value' mapping entries (e.g. 'inherits:', 'formatter:', 'headings:').","Remove any leading '- ' sequence items at column 0.","Compare the file header against a known-good locale file."],"exampleFix":"# before — root is a sequence\n- inherits: en\n- formatter: default\n\n# after — root is a mapping\ninherits: en\nformatter: default","handlingStrategy":"validation","validationCode":"import yaml, pathlib\nlocales_dir = pathlib.Path('src/Humanizer/Locales')\nfor f in locales_dir.rglob('*.yml'):\n    data = yaml.safe_load(f.read_text())\n    if not isinstance(data, dict):\n        print(f'{f.name}: YAML root must be a mapping, got {type(data).__name__}')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Every locale YAML file must be a flat mapping of feature keys at the top level.","Never start a locale file with a sequence item ('- ').","Run a standard YAML parser as a pre-commit check to verify the root is a mapping."],"tags":["locale","yaml","source-generator","parser","root"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}