Humanizr/Humanizer · critical · InvalidOperationException
Locale '{localeCode}.surfaces.number.formatting' defines uns
Error message
Locale '{localeCode}.surfaces.number.formatting' defines unsupported property '{property}'. Supported properties: decimalSeparator, negativeSign, groupSeparator. What it means
Thrown by ValidateNumberFormattingBlock when surfaces.number.formatting in a locale YAML contains a property other than the three allowed keys: decimalSeparator, negativeSign, groupSeparator. The canonical schema is closed, so any extra key (including renamed or locale-specific ones) is rejected at build time to keep formatting behavior predictable.
Source
Thrown at src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs:366
{
if (value is not SimpleYamlScalar scalar || !scalar.IsString)
{
throw new InvalidOperationException(
$"Locale '{localeCode}.{path}.{key}' must be a string.");
}
if (!allowEmpty && string.IsNullOrEmpty(scalar.Value))
{
throw new InvalidOperationException(
$"Locale '{localeCode}.{path}.{key}' must be a non-empty string. Omit unused sparse slots instead.");
}
}
static void ValidateNumberFormattingBlock(string localeCode, SimpleYamlMapping formatting)
{
foreach (var property in formatting.Values.Keys.Where(static property => property is not ("decimalSeparator" or "negativeSign" or "groupSeparator")))
{
throw new InvalidOperationException(
$"Locale '{localeCode}.surfaces.number.formatting' defines unsupported property '{property}'. Supported properties: decimalSeparator, negativeSign, groupSeparator.");
}
ValidateOptionalFormattingProperty(localeCode, formatting, "decimalSeparator");
ValidateOptionalFormattingProperty(localeCode, formatting, "negativeSign");
ValidateOptionalFormattingProperty(localeCode, formatting, "groupSeparator");
if (formatting.Values.Count == 0)
{
throw new InvalidOperationException(
$"Locale '{localeCode}.surfaces.number.formatting' must define at least one property.");
}
}
static void ValidateOptionalFormattingProperty(string localeCode, SimpleYamlMapping formatting, string propertyName)
{
if (!formatting.TryGetValue(propertyName, out var value))
{View on GitHub (pinned to ffc2b77c0f)
Solutions
- Remove the unsupported property '{property}' from surfaces.number.formatting.
- If you need a real new formatting dimension, extend SupportedSurfaceNames/ValidateNumberFormattingBlock in the source generator rather than smuggling it into YAML.
- Confirm only decimalSeparator, negativeSign, and/or groupSeparator remain, then rebuild.
Example fix
# before
number:
formatting:
decimalSeparator: ","
thousandsSeparator: "." # unsupported
# after
number:
formatting:
decimalSeparator: ","
groupSeparator: "." Defensive patterns
Strategy: validation
Validate before calling
# Validate the number.formatting keys against the allow-list before building. $allowed = 'decimalSeparator','negativeSign','groupSeparator' $yaml = Get-Content src/Humanizer/Locales/<code>.yml -Raw # (Parse with any YAML module) and assert every key under number.formatting is in $allowed.
Prevention
- Remember the formatting surface is closed: only decimalSeparator, negativeSign, groupSeparator.
- Use 'groupSeparator', not the legacy 'thousandsSeparator'.
- If a new formatting dimension is needed, extend ValidateNumberFormattingBlock in the generator first.
When it happens
Trigger: A contributor adds a property like 'percentSign', 'currencySymbol', or 'thousandsSeparator' under surfaces.number.formatting. The loop at CanonicalLocaleAuthoring.cs:364-369 flags any key not in the allow-list and throws.
Common situations: Porting from ICU/CLDR data that includes extra number symbols; renaming 'groupSeparator' to the older 'thousandsSeparator'; pasting a formatting block from another library's config.
Related errors
- Locale '{localeCode}.surfaces.number.formatting' must define
- Locale '{localeCode}.surfaces.number.formatting.{propertyNam
- Locale '{localeCode}.surfaces.number.formatting.{propertyNam
- Locale '{localeCode}.{path}' defines duplicate numeric minut
- Locale '{localeCode}.{path}.{key}' must be a string.
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/e7694b4d7b05518e.
Report an issue: GitHub.