{"record":{"id":"3893efd606eb2123","repo":"Humanizr/Humanizer","slug":"locale-localecode-surfaces-number-formatting-m-3893ef","errorCode":null,"errorMessage":"Locale '{localeCode}.surfaces.number.formatting' must define at least one property.","messagePattern":"Locale '(.+?)\\.surfaces\\.number\\.formatting' must define at least one property\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs","lineNumber":376,"sourceCode":"                    $\"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\n            ValidateOptionalFormattingProperty(localeCode, formatting, \"decimalSeparator\");\n            ValidateOptionalFormattingProperty(localeCode, formatting, \"negativeSign\");\n            ValidateOptionalFormattingProperty(localeCode, formatting, \"groupSeparator\");\n\n            if (formatting.Values.Count == 0)\n            {\n                throw new InvalidOperationException(\n                    $\"Locale '{localeCode}.surfaces.number.formatting' must define at least one property.\");\n            }\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))","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs#L358-L394","documentation":"Thrown by ValidateNumberFormattingBlock when the surfaces.number.formatting mapping exists but is empty. The generator requires at least one of the three supported properties (decimalSeparator, negativeSign, groupSeparator) because an empty formatting block carries no information and usually signals a leftover placeholder.","triggerScenarios":"A locale YAML declares 'number:\\n  formatting: {}' or 'formatting:' with no children. After allow-list filtering, formatting.Values.Count is 0 at CanonicalLocaleAuthoring.cs:374-378 and the build fails.","commonSituations":"Adding a 'formatting:' header while translating then forgetting to populate it; clearing all three separators during a refactor; an automated migration that stripped values but kept the key.","solutions":["Populate at least one supported property (most commonly decimalSeparator) under surfaces.number.formatting.","If the locale should not override formatting, remove the entire 'formatting' key so defaults apply.","Rebuild to confirm the error clears."],"exampleFix":"# before\nnumber:\n  formatting:\n# after\nnumber:\n  formatting:\n    decimalSeparator: \",\"","handlingStrategy":"validation","validationCode":"# If surfaces.number.formatting exists, it must contain >=1 supported property.\n# Pre-build check: ensure the block is either absent or non-empty.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Populate at least decimalSeparator whenever you add a 'formatting:' block.","If not overriding formatting, omit the whole 'number.formatting' key.","Run 'dotnet build' after locale edits to catch empty blocks."],"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"}