{"record":{"id":"e009f886a6a014df","repo":"Humanizr/Humanizer","slug":"locale-localecode-surfaces-number-formatting-p-e009f8","errorCode":null,"errorMessage":"Locale '{localeCode}.surfaces.number.formatting.{propertyName}' must be a non-empty string.","messagePattern":"Locale '(.+?)\\.surfaces\\.number\\.formatting\\.(.+?)' must be a non-empty string\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs","lineNumber":396,"sourceCode":"            }\n        }\n\n        static void ValidateOptionalFormattingProperty(string localeCode, SimpleYamlMapping formatting, string propertyName)\n        {\n            if (!formatting.TryGetValue(propertyName, out var value))\n            {\n                return;\n            }\n\n            if (value is not SimpleYamlScalar scalar)\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.surfaces.number.formatting.{propertyName}' must be a scalar string, not a mapping or sequence.\");\n            }\n\n            if (string.IsNullOrEmpty(scalar.Value))\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.surfaces.number.formatting.{propertyName}' must be a non-empty string.\");\n            }\n        }\n\n        static void AddOrdinalFeatures(\n            string localeCode,\n            SimpleYamlMapping ordinalSurface,\n            ImmutableDictionary<string, SimpleYamlValue>.Builder features)\n        {\n            foreach (var property in ordinalSurface.Values.Keys.Where(static property => property is not (\"numeric\" or \"date\" or \"dateOnly\")))\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.surfaces.ordinal' defines unsupported property '{property}'. Supported properties: numeric, date, dateOnly.\");\n            }\n\n            if (ordinalSurface.TryGetValue(\"numeric\", out var numericValue))\n            {\n                if (numericValue is not SimpleYamlMapping numericMapping)","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs#L378-L414","documentation":"Thrown by ValidateOptionalFormattingProperty when decimalSeparator, negativeSign, or groupSeparator is a scalar string but empty. An empty separator is meaningless for number formatting and would corrupt output, so the canonical schema forbids it at build time.","triggerScenarios":"A locale YAML writes 'decimalSeparator:' or 'groupSeparator: \"\"' with no value. ValidateOptionalFormattingProperty checks string.IsNullOrEmpty at CanonicalLocaleAuthoring.cs:394-398 and fails.","commonSituations":"Clearing a separator value while editing; a locale that intentionally omits grouping using an empty string instead of removing the key; copy-paste leaving blank values.","solutions":["Provide a concrete single-character value (e.g. 'groupSeparator: \".\"').","If the locale should not override that separator, remove the property entirely rather than leaving it empty.","Rebuild to confirm the formatting block is valid."],"exampleFix":"# before\nnumber:\n  formatting:\n    decimalSeparator:\n# after\nnumber:\n  formatting:\n    decimalSeparator: \",\"","handlingStrategy":"validation","validationCode":"# Detect empty formatting properties:\nSelect-String -Path src/Humanizer/Locales/<code>.yml -Pattern '(decimalSeparator|negativeSign|groupSeparator):\\s*(\"\"|\\s*$)'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Provide a concrete character for each separator you declare.","Remove a separator property instead of leaving it empty when the locale should not override it.","Build after edits to surface the offending {propertyName}."],"tags":["localization","yaml","source-generator","locale","build","number-formatting"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}