{"record":{"id":"cfb15c79aa9dc8c8","repo":"Humanizr/Humanizer","slug":"locale-localecode-grammar-must-be-a-mapping","errorCode":null,"errorMessage":"Locale '{localeCode}.grammar' must be a mapping.","messagePattern":"Locale '(.+?)\\.grammar' must be a mapping\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs","lineNumber":757,"sourceCode":"                        kind: scalar.Value,\n                        argument: null,\n                        profileName: null,\n                        profileRoot: default,\n                        usesGeneratedProfile: false),\n                    SimpleYamlMapping mapping => CreateMappedFeature(localeCode, featureName, mapping),\n                    _ => throw new InvalidOperationException(\n                        $\"Feature '{featureName}' in locale '{localeCode}' must be a scalar or mapping.\")\n                };\n        }\n\n        static SimpleYamlMapping? ResolveGrammar(\n            string localeCode,\n            ImmutableDictionary<string, SimpleYamlValue> features)\n        {\n            return !features.TryGetValue(\"grammar\", out var grammarValue)\n                ? null\n                : grammarValue as SimpleYamlMapping\n                ?? throw new InvalidOperationException($\"Locale '{localeCode}.grammar' must be a mapping.\");\n        }\n\n        static LocalePhraseCatalog? ResolvePhraseCatalog(\n            string localeCode,\n            ImmutableDictionary<string, SimpleYamlValue> features)\n        {\n            var preserveDurationCaseForms =\n                features.TryGetValue(\"formatter\", out var formatterValue) &&\n                formatterValue is SimpleYamlMapping formatter &&\n                formatter.GetScalar(\"casePluralRule\") is not null;\n\n            return !features.TryGetValue(\"phrases\", out var phraseValue)\n                ? null\n                : phraseValue is SimpleYamlMapping mapping\n                ? LocalePhraseNormalization.Create(localeCode, mapping, preserveDurationCaseForms)\n                : throw new InvalidOperationException($\"Locale '{localeCode}.phrases' must be a mapping.\");\n        }\n","sourceCodeStart":739,"sourceCodeEnd":775,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs#L739-L775","documentation":"The 'grammar' feature must be a YAML mapping (object) because it contains keyed grammar configuration such as cases and genders. A scalar or sequence value cannot supply those sub-keys, so the resolver rejects it.","triggerScenarios":"A locale file sets 'grammar:' to a bare scalar (e.g. 'grammar: latin') or to a sequence instead of a nested mapping of grammar rules.","commonSituations":"Misunderstanding the grammar schema; copy-pasting a scalar feature value into the grammar slot; truncating a grammar block during editing.","solutions":["Change the 'grammar:' value to a mapping with the expected sub-keys.","Reference an existing locale with grammar (e.g. 'ru.yml', 'ar.yml') for the correct structure.","If the locale does not need grammar rules, remove the 'grammar:' key entirely rather than setting a placeholder."],"exampleFix":"# before\ngrammar: slavic\n\n# after\ngrammar:\n  cases:\n    nominative: 0\n    genitive: 1","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 isinstance(data, dict) and 'grammar' in data:\n        if not isinstance(data['grammar'], dict):\n            print(f'{f.name}: grammar must be a mapping, got {type(data[\"grammar\"]).__name__}')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding grammar rules, always nest sub-keys under 'grammar:' as a mapping.","Remove the grammar key entirely if the locale has no grammar data rather than leaving a scalar.","Reference 'ru.yml' or 'ar.yml' for the correct grammar mapping structure."],"tags":["locale","yaml","source-generator","grammar","schema"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}