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

  1. Ensure the GrammaticalGender value is always one of Masculine, Feminine, or Neuter — validate at the trust boundary before calling ToWords/ConvertToOrdinal.
  2. If the value originates from deserialization or an integer source, guard with Enum.IsDefined(typeof(GrammaticalGender), value) before passing it.
  3. 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

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


AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13). Data as JSON: /api/errors/89b3e9351f7fa9fe. Report an issue: GitHub.