Humanizr/Humanizer · error · InvalidOperationException
Billion-word cardinal strategy requires a plural billion wor
Error message
Billion-word cardinal strategy requires a plural billion word.
What it means
Thrown when a locale's cardinal scale declares billionStrategy: 'billion-word' but omits the billionPluralWord property. The BillionStrategyCardinalScale row needs both singular and plural billion terms to pluralize counts of billions; the generator refuses to emit an incomplete row. It is the sibling check to the singular-billion-word error.
Source
Thrown at src/Humanizer.SourceGenerators/Common/GenerationHelpers.cs:738
first = false;
}
builder.Append(" }");
return builder.ToString();
}
static string CreateLegacyBillionStrategyCardinalScaleArrayExpression(JsonElement cardinalElement)
{
var millionScale = $"new(1000000UL, {QuoteLiteral(GetRequiredString(cardinalElement, "millionSingularWord"))}, {QuoteLiteral(GetRequiredString(cardinalElement, "millionPluralWord"))})";
if (GetRequiredString(cardinalElement, "billionStrategy") != "billion-word")
{
return $"new BillionStrategyCardinalScale[] {{ {millionScale} }}";
}
var billionSingular = GetOptionalString(cardinalElement, "billionSingularWord")
?? throw new InvalidOperationException("Billion-word cardinal strategy requires a singular billion word.");
var billionPlural = GetOptionalString(cardinalElement, "billionPluralWord")
?? throw new InvalidOperationException("Billion-word cardinal strategy requires a plural billion word.");
return $"new BillionStrategyCardinalScale[] {{ new(1000000000UL, {QuoteLiteral(billionSingular)}, {QuoteLiteral(billionPlural)}), {millionScale} }}";
}
static string CreateContractedOneScaleArrayExpression(JsonElement arrayElement)
{
if (arrayElement.ValueKind != JsonValueKind.Array)
{
throw new InvalidOperationException("Expected JSON array.");
}
var builder = new StringBuilder("new ContractedOneScaleNumberToWordsConverter.Scale[] { ");
var first = true;
foreach (var item in arrayElement.EnumerateArray())
{
if (item.ValueKind != JsonValueKind.Object)
{
continue;View on GitHub (pinned to ffc2b77c0f)
Solutions
- Add the 'billionPluralWord' key alongside billionSingularWord under numberToWords cardinal (e.g. billionPluralWord: 'billions').
- If the locale does not distinguish singular/plural billion forms, set billionStrategy to a non-'billion-word' value so neither key is required.
- Mirror the exact key set from a working billion-word locale such as en.yml.
Example fix
# before cardinal: billionStrategy: 'billion-word' billionSingularWord: 'un milliard' # after cardinal: billionStrategy: 'billion-word' billionSingularWord: 'un milliard' billionPluralWord: 'milliards'
Defensive patterns
Strategy: validation
Validate before calling
# Ensure the plural billion word accompanies the singular one: # rg "billionSingularWord" src/Humanizer/Locales/<code>.yml # rg "billionPluralWord" src/Humanizer/Locales/<code>.yml # Both must return a match within the cardinal block when billionStrategy is 'billion-word'.
Prevention
- Add billionSingularWord and billionPluralWord as a pair; never one without the other.
- If the locale does not pluralize billions, choose a non-'billion-word' strategy instead.
- Run 'dotnet build' after editing cardinal scales to catch missing plural words early.
When it happens
Trigger: A locale YAML sets numberToWords cardinal.billionStrategy to 'billion-word' and provides billionSingularWord but not billionPluralWord. The throw happens immediately after the singular-word null-coalesce in CreateLegacyBillionStrategyCardinalScaleArrayExpression.
Common situations: A contributor adds the singular billion word while editing but forgets the plural, or copies a locale where the two keys diverge in naming. Surfaces as a CS8785 generator failure at build time, often right after the singular-word check is satisfied.
Related errors
- Billion-word cardinal strategy requires a singular billion w
- Property '{propertyName}' must be a string, array, or mappin
- Property '{propertyName}' must be a mapping.
- Expected JSON array or mapping.
- Inverted tens token '{property.Name}' must map to an integer
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/1782a9a42a4cb6d2.
Report an issue: GitHub.