{"record":{"id":"664d59ba748a3447","repo":"Humanizr/Humanizer","slug":"locale-localecode-path-key-must-be-a-strin","errorCode":null,"errorMessage":"Locale '{localeCode}.{path}.{key}' must be a string.","messagePattern":"Locale '(.+?)\\.(.+?)\\.(.+?)' must be a string\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs","lineNumber":351,"sourceCode":"                }\n\n                ValidateMinuteWordValue(localeCode, path, entry.Key, entry.Value, allowEmpty: false);\n                normalizedValues[canonicalKey] = entry.Value;\n            }\n\n            return new SimpleYamlMapping(normalizedValues.ToImmutable());\n        }\n\n        static void ValidateMinuteWordValue(\n            string localeCode,\n            string path,\n            string key,\n            SimpleYamlValue value,\n            bool allowEmpty)\n        {\n            if (value is not SimpleYamlScalar scalar || !scalar.IsString)\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.{path}.{key}' must be a string.\");\n            }\n\n            if (!allowEmpty && string.IsNullOrEmpty(scalar.Value))\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.{path}.{key}' must be a non-empty string. Omit unused sparse slots instead.\");\n            }\n        }\n\n        static void ValidateNumberFormattingBlock(string localeCode, SimpleYamlMapping formatting)\n        {\n            foreach (var property in formatting.Values.Keys.Where(static property => property is not (\"decimalSeparator\" or \"negativeSign\" or \"groupSeparator\")))\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.surfaces.number.formatting' defines unsupported property '{property}'. Supported properties: decimalSeparator, negativeSign, groupSeparator.\");\n            }\n","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs#L333-L369","documentation":"Thrown by ValidateMinuteWordValue when a clock minute slot's value is not a YAML scalar string (it is a mapping, a sequence, or a non-string token). The minute-words table must map each integer key to a single human-readable string, so any structured value is rejected at build time.","triggerScenarios":"A locale YAML minute entry is indented as a nested mapping/sequence (e.g. '5:\\n  value: five') or is a quoted multi-line block, so SimpleYamlValue is not a SimpleYamlScalar with IsString. Detected at CanonicalLocaleAuthoring.cs:349-353.","commonSituations":"Pasting from a richer locale format that nests metadata under each minute; mis-indenting a YAML value so it becomes a child mapping; converting an array-based locale representation into the canonical mapping form.","solutions":["Replace the minute's value with a single inline string scalar, e.g. '5: five minutes'.","Check indentation: the minute key and its value must sit on the same line or be a plain folded scalar, not a nested block.","Re-run 'dotnet build' to confirm ValidateMinuteWordValue no longer fires for {path}.{key}."],"exampleFix":"# before\nminutes:\n  5:\n    word: five minutes\n# after\nminutes:\n  5: five minutes","handlingStrategy":"validation","validationCode":"# Ensure every minute value is a plain scalar, not a nested mapping/sequence.\n# In your editor, each line under 'minutes:' must read '<int>: <string>'.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep minute values inline: '5: five minutes', never a nested block.","Run 'dotnet build' after editing the clock surface to catch non-scalar values early.","Mirror the structure of a known-good locale (e.g. src/Humanizer/Locales/en.yml) when translating."],"tags":["localization","yaml","source-generator","locale","build"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}