Humanizr/Humanizer · error · ArgumentOutOfRangeException
gender
Error message
gender
What it means
This ArgumentOutOfRangeException is a defensive exhaustiveness guard inside GetCardinalUnitEnding, a static method on TerminalOrdinalScaleNumberToWordsConverter. The switch only patterns Masculine and Feminine after NormalizeGender has already mapped Neuter to Masculine, so every valid GrammaticalGender value is consumed before the discard arm. The throw fires only when the caller supplies an enum value outside the three declared members (e.g. an unchecked cast such as (GrammaticalGender)42).
Source
Thrown at src/Humanizer/Localisation/NumberToWords/TerminalOrdinalScaleNumberToWordsConverter.cs:215
/// Returns the cardinal ending for a unit stem.
/// </summary>
static string GetCardinalUnitEnding(GrammaticalGender gender, int number)
{
return NormalizeGender(gender) switch
{
GrammaticalGender.Masculine => number switch
{
1 => "s",
< 10 when number != 3 => "i",
_ => string.Empty
},
GrammaticalGender.Feminine => number switch
{
1 => "a",
< 10 when number != 3 => "as",
_ => string.Empty
},
_ => throw new ArgumentOutOfRangeException(nameof(gender))
};
}
/// <summary>
/// Returns the ordinal suffix for the requested gender.
/// </summary>
string GetOrdinalSuffix(GrammaticalGender gender) =>
NormalizeGender(gender) switch
{
GrammaticalGender.Masculine => profile.MasculineOrdinalSuffix,
GrammaticalGender.Feminine => profile.FeminineOrdinalSuffix,
_ => throw new ArgumentOutOfRangeException(nameof(gender))
};
static GrammaticalGender NormalizeGender(GrammaticalGender gender) =>
gender == GrammaticalGender.Neuter ? GrammaticalGender.Masculine : gender;
static ulong GetAbsoluteValue(long value) =>View on GitHub (pinned to ffc2b77c0f)
Solutions
- Ensure the GrammaticalGender value is always one of Masculine, Feminine, or Neuter — validate at the trust boundary before calling ToWords/ConvertToOrdinal.
- If the value originates from deserialization or an integer source, guard with Enum.IsDefined(typeof(GrammaticalGender), value) before passing it.
- Map any unknown gender to a safe default (typically GrammaticalGender.Masculine) at the call site so invalid upstream data degrades gracefully instead of crashing.
Example fix
// before
var gender = (GrammaticalGender)userInput;
return number.ToWords(gender, culture);
// after
if (!Enum.IsDefined(typeof(GrammaticalGender), userInput))
throw new ArgumentOutOfRangeException(nameof(userInput));
var gender = (GrammaticalGender)userInput;
return number.ToWords(gender, culture); Defensive patterns
Strategy: validation
Validate before calling
bool IsValidGender(GrammaticalGender gender) =>
gender is GrammaticalGender.Masculine
or GrammaticalGender.Feminine
or GrammaticalGender.Neuter;
// or for untrusted integer sources:
bool IsValidGenderCode(int code) =>
Enum.IsDefined(typeof(GrammaticalGender), code); Type guard
static bool IsDefinedGender(GrammaticalGender gender) =>
Enum.IsDefined(typeof(GrammaticalGender), gender); Try / catch
try
{
return number.ToWords(gender, culture);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "gender")
{
return number.ToWords(GrammaticalGender.Masculine, culture);
} Prevention
- Validate GrammaticalGender at every boundary where the value originates from external or serialized data.
- Prefer binding enums by name in JSON/deserialization rather than by raw integer.
- Use Enum.IsDefined in integration layers to reject phantom enum values before they reach Humanizer.
- Enable nullable reference types and treat enum validation as a trust-boundary concern.
When it happens
Trigger: Calling Convert(number, gender) or ConvertToOrdinal(number, gender) on a locale backed by TerminalOrdinalScaleNumberToWordsConverter with a GrammaticalGender value produced by an invalid cast or deserialized from corrupt data rather than one of the declared enum literals.
Common situations: Deserializing a GrammaticalGender from an integer column or JSON payload that was never validated; forwarding a gender typed as int or byte through a boundary without range-checking; unit tests that synthesize enum values via reflection or unchecked casts.
Related errors
- gender
- gender
- Failed to project metric scale words for locale '{locale.Loc
- Array-backed metric scale word contracts require a value pro
- Unsupported number-to-words contract member kind '{member.Ki
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/89b3e9351f7fa9fe.
Report an issue: GitHub.