Humanizr/Humanizer · error · InvalidOperationException
Property '{propertyName}' must be a string, array, or mappin
Error message
Property '{propertyName}' must be a string, array, or mapping (got {property.ValueKind}). What it means
Thrown by CreateUnitLeadingCompoundOrdinalPairExpression when an ordinalSingular or ordinalPlural property has an unsupported JSON value kind (not string, array, or object). The generator supports three shapes for an ordinal pair but rejects booleans, numbers, or null, because it cannot map them to the two-element string[] output.
Source
Thrown at src/Humanizer.SourceGenerators/Common/GenerationHelpers.cs:1015
RequiredInt64Value("value"),
BooleanValue("addSpaceBeforeNextPart"),
OptionalEnumValue("countGender", "GrammaticalGender", "masculine"),
RequiredStringValue("singularCardinal"),
RequiredStringValue("pluralCardinalFormat"),
static element => CreateUnitLeadingCompoundOrdinalPairExpression(element, "ordinalSingular"),
static element => CreateUnitLeadingCompoundOrdinalPairExpression(element, "ordinalPlural"),
OptionalStringValue("countWordFormNextWord"));
static string CreateUnitLeadingCompoundOrdinalPairExpression(JsonElement element, string propertyName)
{
return !element.TryGetProperty(propertyName, out var property)
? throw new InvalidOperationException($"Missing required property '{propertyName}'.")
: property.ValueKind switch
{
JsonValueKind.String => "new string[] { " + QuoteLiteral(property.GetString()!) + ", " + QuoteLiteral(property.GetString()!) + " }",
JsonValueKind.Array => CreateStringArrayExpression(property),
JsonValueKind.Object => CreateTerminalContinuingStringArrayExpression(property, propertyName),
_ => throw new InvalidOperationException($"Property '{propertyName}' must be a string, array, or mapping (got {property.ValueKind}).")
};
}
static string CreateTerminalContinuingStringArrayExpression(JsonElement objectElement, string propertyName)
{
return objectElement.ValueKind != JsonValueKind.Object
? throw new InvalidOperationException($"Property '{propertyName}' must be a mapping.")
: "new string[] { " +
QuoteLiteral(GetRequiredString(objectElement, "terminal")) + ", " +
QuoteLiteral(GetRequiredString(objectElement, "continuing")) +
" }";
}
static string CreateConjoinedGenderedScaleArrayExpression(JsonElement arrayElement)
=> CreateTypedConstructorArrayExpression(
"ConjoinedGenderedScale",
arrayElement,
RequiredInt64Value("divisor"),View on GitHub (pinned to ffc2b77c0f)
Solutions
- Open the locale YAML and change the flagged ordinalSingular/ordinalPlural value to a quoted string, a sequence of strings, or a mapping with 'terminal' and 'continuing'.
- If the word looks numeric, wrap it in quotes (e.g. 'ordinalSingular: "21"') so YAML treats it as a string.
- Rebuild to confirm the generator accepts the corrected shape.
Example fix
# before ordinalSingular: 21 # after ordinalSingular: 'dwudziesty pierwszy'
Defensive patterns
Strategy: validation
Validate before calling
# Ensure ordinal pair values are quoted strings, sequences, or mappings: # rg "ordinalSingular:|ordinalPlural:" src/Humanizer/Locales/<code>.yml # No value should be a bare number, boolean, or null.
Prevention
- Quote any ordinal word that could be mistaken for a number (e.g. 'ordinalSingular: "21"').
- Use only the three supported shapes: string, sequence, or terminal/continuing mapping.
- Build locally after ordinal edits to catch kind mismatches.
When it happens
Trigger: A locale YAML provides an ordinalSingular or ordinalPlural entry whose YAML value parses to a JSON number, boolean, or null rather than a scalar/sequence/mapping. The switch expression falls through to the default arm and throws, naming the property and the offending ValueKind.
Common situations: A contributor writes 'ordinalSingular: true' or 'ordinalSingular: 21' by mistake, or leaves a bare null. Less commonly, a YAML quoting slip turns a word into a number. Surfaces at build time via the source generator.
Related errors
- Property '{propertyName}' must be a mapping.
- Billion-word cardinal strategy requires a singular billion w
- Billion-word cardinal strategy requires a plural billion wor
- 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/cbfb486151d3b52f.
Report an issue: GitHub.