Humanizr/Humanizer · error · ArgumentException

Unrecognized number word: {unrecognizedWord}

Error message

Unrecognized number word: {unrecognizedWord}

What it means

SuffixScaleWordsToNumberConverter.Convert throws this ArgumentException at line 19 when TryConvert fails to map the phrase under the suffix-scale grammar. This converter also accepts a bare invariant integer (long.TryParse) as a fast path, and caps work via MinimumParseWork/ParseWorkPerCharacter. Only Convert raises it; Try overloads return false with the unrecognized token.

Source

Thrown at src/Humanizer/Localisation/WordsToNumber/SuffixScaleWordsToNumberConverter.cs:19

namespace Humanizer;

/// <summary>
/// Parses languages that place scale words after the quantity they modify.
/// </summary>
internal class SuffixScaleWordsToNumberConverter(SuffixScaleWordsToNumberProfile profile) : GenderlessWordsToNumberConverter
{
    const int MaximumParseDepth = 128;
    const int ParseWorkPerCharacter = 32;
    // Short ambiguous compounds need room to preserve the parser's historical backtracking order.
    const int MinimumParseWork = 1_000_000;
    readonly SuffixScaleWordsToNumberProfile 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.");
        }

        if (long.TryParse(words.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out parsedValue))

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Use TryToNumber(words, out var n, culture, out var bad) instead of ToNumber.
  2. Inspect bad and correct the phrase or culture.
  3. For pure digit strings, pass them directly (the invariant-integer fast path avoids the grammar).

Example fix

// before
var n = phrase.ToNumber(culture);
// after
if (phrase.TryToNumber(out var n, culture, out var bad))
    Use(n);
else
    Warn($"unrecognized: {bad}");
Defensive patterns

Strategy: validation

Validate before calling

if (!words.TryToNumber(out var n, culture, out var unrecognized))
    return Result.Fail($"unrecognized token: {unrecognized}");
return Result.Ok(n);

Try / catch

try { var n = words.ToNumber(culture); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unrecognized number word"))
    { /* handle */ }

Prevention

When it happens

Trigger: Calling ToNumber with tokens outside the suffix-scale map that are also not a bare integer (the fast path), or inputs triggering the backtracking work budget. Fires at line 19 when TryConvert returns false.

Common situations: Wrong culture; user free text; pathological inputs relying on historical backtracking order; misspelled or foreign tokens.

Related errors


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