Humanizr/Humanizer · error · ArgumentException

Unrecognized number word: {unrecognizedWord}

Error message

Unrecognized number word: {unrecognizedWord}

What it means

This ArgumentException is thrown by CompoundScaleWordsToNumberConverter.Convert (the throwing entry point) when TryConvert returns false. TryConvert returns false when the normalized input phrase contains a token that is not in the locale's cardinal map, ordinal map, tens stems, or large-scale words. The unrecognized word is included in the message for diagnostics. This converter is used by locales that compose cardinals from direct tokens, optional tens stems, and explicit scale words (thousand, million, etc.).

Source

Thrown at src/Humanizer/Localisation/WordsToNumber/CompoundScaleWordsToNumberConverter.cs:26

/// - optional ordinal forms derived from either explicit YAML or a generated number-to-words bridge
///
/// The parser normalizes the input, strips a configured negative prefix, then resolves either an
/// exact ordinal token or a cardinal phrase assembled from token groups and scale multipliers.
/// The end result should be the numeric value the locale phrase denotes, not merely a best-effort
/// token sum.
/// </summary>
internal class CompoundScaleWordsToNumberConverter(CompoundScaleWordsToNumberProfile profile) : GenderlessWordsToNumberConverter
{
    const int MaximumParseDepth = 128;

    readonly CompoundScaleWordsToNumberProfile profile = profile;

    /// <inheritdoc />
    public override long Convert(string words)
    {
        if (!TryConvert(words, out var parsedValue, out var unrecognizedWord))
        {
            throw new ArgumentException($"Unrecognized number word: {unrecognizedWord}");
        }

        return parsedValue;
    }

    /// <inheritdoc />
    public override bool TryConvert(string words, out long parsedValue) =>
        TryConvert(words, out parsedValue, out _);

    /// <inheritdoc />
    public override bool TryConvert(string words, out long parsedValue, out string? unrecognizedWord)
    {
        if (string.IsNullOrWhiteSpace(words))
        {
            throw new ArgumentException("Input words cannot be empty.");
        }

        var normalized = Normalize(words);

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Use TryToNumber(words, out value, culture, out unrecognizedWord) instead of ToNumber so unrecognized input returns false instead of throwing.
  2. Pre-validate the phrase against the locale's expected vocabulary or constrain user input to known number words.
  3. Check that the CultureInfo passed matches the language of the words; feeding English words to a non-English culture always fails.
  4. Normalize user input (strip unexpected punctuation, correct casing) before parsing if the source is untrusted.

Example fix

// before
long value = "twnty".ToNumber(new CultureInfo("en"));

// after
if (!"twnty".TryToNumber(out var value, new CultureInfo("en"), out var bad))
    Console.WriteLine($"Unrecognized: {bad}");
Defensive patterns

Strategy: try-catch

Validate before calling

// Use the non-throwing API instead
bool canParse = words.TryToNumber(out var value, culture, out var unrecognized);
if (!canParse)
    Console.WriteLine($"Cannot parse: unknown token '{unrecognized}'");

Type guard

// Check if the phrase is likely parseable by sampling known tokens
static bool LooksLikeNumberWords(string words, CultureInfo culture)
{
    if (string.IsNullOrWhiteSpace(words)) return false;
    return words.TryToNumber(out _, culture, out _);
}

Try / catch

try
{
    return words.ToNumber(culture);
}
catch (ArgumentException ex) when (ex.Message.Contains("Unrecognized number word"))
{
    // Log and handle the unrecognized input
    return 0;
}

Prevention

When it happens

Trigger: Calling "words".ToNumber(culture) for a compound-scale locale with a phrase that includes a misspelled word, a word from a different language, punctuation the normalizer does not strip, or a number outside the locale's authored vocabulary.

Common situations: User-typed free-text input fed directly into ToNumber without pre-validation; copy-paste from a source that includes smart quotes or Unicode punctuation not handled by the normalizer; locale mismatch (passing English words to a non-English culture); using an ordinal or large-scale word the locale YAML did not author.

Related errors


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