{"record":{"id":"732a49d2815add70","repo":"Humanizr/Humanizer","slug":"gender-732a49","errorCode":null,"errorMessage":"gender","messagePattern":"gender","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/NumberToWords/UnitLeadingCompoundNumberToWordsConverter.cs","lineNumber":258,"sourceCode":"\n    string GetCompoundUnit(int number) => profile.CompoundUnitsMap[number];\n\n    // The tens joiner itself may need a transform such as the Eifeler rule depending on the next word.\n    string GetTensJoiner(string nextWord) =>\n        profile.TensJoinerTransform switch\n        {\n            CompoundTensJoinerTransform.None => profile.TensJoiner,\n            CompoundTensJoinerTransform.Eifeler => EifelerRule.ApplyIfNeeded(profile.TensJoiner, nextWord),\n            _ => throw new InvalidOperationException(\"Unknown unit-leading-compound tens joiner transform.\")\n        };\n\n    string GetEndingForGender(GrammaticalGender gender) =>\n        gender switch\n        {\n            GrammaticalGender.Masculine => profile.MasculineOrdinalEnding,\n            GrammaticalGender.Feminine => profile.FeminineOrdinalEnding,\n            GrammaticalGender.Neuter => profile.NeuterOrdinalEnding,\n            _ => throw new ArgumentOutOfRangeException(nameof(gender))\n        };\n}\n\n/// <summary>\n/// Immutable generated profile for <see cref=\"UnitLeadingCompoundNumberToWordsConverter\"/>.\n/// </summary>\n/// <param name=\"zeroWord\">The cardinal zero word.</param>\n/// <param name=\"minusWord\">The word used to prefix negative values.</param>\n/// <param name=\"masculineOne\">The masculine form of one.</param>\n/// <param name=\"feminineOne\">The feminine form of one.</param>\n/// <param name=\"neuterOne\">The neuter form of one.</param>\n/// <param name=\"feminineTwo\">The optional feminine form of two.</param>\n/// <param name=\"tensJoiner\">The base joiner inserted between the unit and tens stem.</param>\n/// <param name=\"tensJoinerTransform\">The transform applied to <paramref name=\"tensJoiner\"/> before emission.</param>\n/// <param name=\"ordinalStemSuffix\">The shared ordinal stem suffix appended before the gender ending.</param>\n/// <param name=\"masculineOrdinalEnding\">The masculine ordinal ending.</param>\n/// <param name=\"feminineOrdinalEnding\">The feminine ordinal ending.</param>\n/// <param name=\"neuterOrdinalEnding\">The neuter ordinal ending.</param>","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/NumberToWords/UnitLeadingCompoundNumberToWordsConverter.cs#L240-L276","documentation":"This ArgumentOutOfRangeException is the discard arm of GetEndingForGender on UnitLeadingCompoundNumberToWordsConverter (the Luxembourgish family renderer). Unlike the terminal-ordinal converter, this switch explicitly patterns Masculine, Feminine, and Neuter — all three declared GrammaticalGender members — so the discard is only reachable via an enum value carrying an integral outside the declared range, which can only arise from an invalid cast or corrupt deserialization.","triggerScenarios":"Calling ConvertToOrdinal(number, gender) on a locale backed by UnitLeadingCompoundNumberToWordsConverter with a GrammaticalGender value that is not Masculine, Feminine, or Neuter (produced by an unchecked cast or unvalidated external input).","commonSituations":"Forwarding a gender from a loosely typed integration layer (database int, JSON number, dynamic object) into the ordinal API; unit tests using reflection-constructed enum values; deserialization frameworks that bind enums by integer.","solutions":["Validate the gender at the boundary: reject values outside the declared enum range before calling the converter.","Map invalid values to GrammaticalGender.Masculine if graceful degradation is preferred over failing fast.","Bind GrammaticalGender by name (string) during deserialization rather than by raw integer to prevent phantom values."],"exampleFix":"// before\nreturn number.ToOrdinalWords((GrammaticalGender)code, culture);\n\n// after\nvar gender = Enum.IsDefined(typeof(GrammaticalGender), code)\n    ? (GrammaticalGender)code\n    : GrammaticalGender.Masculine;\nreturn number.ToOrdinalWords(gender, culture);","handlingStrategy":"validation","validationCode":"bool IsValidGender(GrammaticalGender gender) =>\n    gender is GrammaticalGender.Masculine\n        or GrammaticalGender.Feminine\n        or GrammaticalGender.Neuter;","typeGuard":"static bool IsDefinedGender(GrammaticalGender gender) =>\n    Enum.IsDefined(typeof(GrammaticalGender), gender);","tryCatchPattern":"try\n{\n    return number.ToOrdinalWords(gender, culture);\n}\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"gender\")\n{\n    return number.ToOrdinalWords(GrammaticalGender.Masculine, culture);\n}","preventionTips":["Validate GrammaticalGender at the boundary where external data enters your code.","Prefer named enum binding over integer binding in deserialization.","Use Enum.IsDefined for any gender sourced from an integer or dynamic type.","Coerce invalid values to Masculine for graceful degradation where the business allows it."],"tags":["argumentoutofrange","grammatical-gender","ordinal","unit-leading-compound","defensive-guard"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}