{"record":{"id":"15eb039692610aff","repo":"Humanizr/Humanizer","slug":"unrecognized-number-word-unrecognizedword-15eb03","errorCode":null,"errorMessage":"Unrecognized number word: {unrecognizedWord}","messagePattern":"Unrecognized number word: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/WordsToNumber/GreedyCompoundWordsToNumberConverter.cs","lineNumber":23,"sourceCode":"/// </summary>\ninternal class GreedyCompoundWordsToNumberConverter(GreedyCompoundWordsToNumberProfile profile) : GenderlessWordsToNumberConverter\n{\n    readonly GreedyCompoundWordsToNumberProfile profile = profile;\n    // Match the longest candidate first so shorter tokens do not steal the prefix of a glued\n    // compound before the parser has a chance to recognize the full token.\n    readonly string[] cardinalTokenOrder = profile.CardinalMap.Keys\n        .OrderByDescending(static key => key.Length)\n        .ToArray();\n    readonly string[] ignoredTokenOrder = profile.IgnoredTokens\n        .OrderByDescending(static key => key.Length)\n        .ToArray();\n\n    /// <inheritdoc />\n    public override long Convert(string words)\n    {\n        if (!TryConvert(words, out var parsedValue, out var unrecognizedWord))\n        {\n            throw new ArgumentException($\"Unrecognized number word: {unrecognizedWord}\");\n        }\n\n        return parsedValue;\n    }\n\n    /// <inheritdoc />\n    public override bool TryConvert(string words, out long parsedValue) =>\n        TryConvert(words, out parsedValue, out _);\n\n    /// <inheritdoc />\n    public override bool TryConvert(string words, out long parsedValue, out string? unrecognizedWord)\n    {\n        if (string.IsNullOrWhiteSpace(words))\n        {\n            throw new ArgumentException(\"Input words cannot be empty.\");\n        }\n\n        var trimmed = words.Trim();","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/WordsToNumber/GreedyCompoundWordsToNumberConverter.cs#L5-L41","documentation":"This ArgumentException is thrown by GreedyCompoundWordsToNumberConverter.Convert when TryConvert fails. This converter handles locales that prefer greedy longest-token matching for glued compounds and ordinal abbreviations (e.g. '21st'). The error fires when the normalized phrase contains a token fragment that does not match any cardinal token, ordinal token, or ordinal abbreviation suffix in the locale's profile.","triggerScenarios":"Calling \"words\".ToNumber(culture) for a greedy-compound locale with a phrase containing an unrecognized word, an ordinal abbreviation with an unsupported suffix, or glued compound fragments that do not match any known token boundary.","commonSituations":"Free-text user input with misspellings; ordinal abbreviations using suffixes not configured for the locale (e.g. '21st' in a locale that only supports '21.'); locale mismatch; Unicode normalization differences (diacritics) when the locale profile does not enable RemoveDiacritics; input with characters the normalization does not strip.","solutions":["Use TryToNumber(words, out value, culture, out unrecognizedWord) for user-facing or untrusted input.","Verify the locale's normalization settings (diacritic removal, character stripping) match the input's encoding.","Inspect the unrecognizedWord to identify the boundary where matching failed.","Constrain or pre-validate user input against the locale's known vocabulary."],"exampleFix":"// before\nlong value = phrase.ToNumber(culture);\n\n// after\nif (!phrase.TryToNumber(out var value, culture, out var bad))\n    Console.WriteLine($\"Unrecognized: {bad}\");","handlingStrategy":"try-catch","validationCode":"bool canParse = words.TryToNumber(out var value, culture, out var unrecognized);\nif (!canParse)\n    Console.WriteLine($\"Unrecognized: {unrecognized}\");","typeGuard":"static bool LooksLikeNumberWords(string words, CultureInfo culture) =>\n    !string.IsNullOrWhiteSpace(words) && words.TryToNumber(out _, culture, out _);","tryCatchPattern":"try\n{\n    return words.ToNumber(culture);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Unrecognized number word\"))\n{\n    return 0;\n}","preventionTips":["Use TryToNumber for user-facing or untrusted input.","Verify the locale's normalization settings (diacritic removal, character stripping) match the input.","Check ordinal abbreviation suffixes are configured if parsing forms like '21st'.","Inspect the unrecognizedWord to locate the failing token."],"tags":["argumentexception","words-to-number","greedy-compound","unrecognized-word","parsing"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}