Humanizr/Humanizer · error · FormatException

Unrecognized decimal number word: {unrecognizedNumber}

Error message

Unrecognized decimal number word: {unrecognizedNumber}

What it means

LocalizedWordsToDecimalNumberConverter.Convert throws this FormatException at line 48 when TryConvert cannot parse the decimal phrase, reporting the first unrecognized token. It differs from the integer 'unrecognized word' throw: this is decimal-specific and uses FormatException. Only the throwing Convert path raises it; TryConvert returns false with the unrecognized token.

Source

Thrown at src/Humanizer/Localisation/WordsToNumber/LocalizedWordsToDecimalNumberConverter.cs:48

        integerConverter = Configurator.GetWordsToNumberConverter(culture);
        allowsJoinedTokens = integerConverter is EastAsianPositionalWordsToNumberConverter;
        allowsEnglishOverflowComposition =
            string.Equals(culture.TwoLetterISOLanguageName, "en", StringComparison.OrdinalIgnoreCase);
        this.negativePrefixes = NormalizePrefixes(negativePrefixes);
        this.negativeSuffixes = NormalizeSuffixes(negativeSuffixes);
        fractionalDigits = CreateFractionalDigits(culture);
    }

    internal string DecimalMarker => decimalMarker;

    /// <inheritdoc />
    public decimal Convert(string words)
    {
        ArgumentNullException.ThrowIfNull(words);

        if (!TryConvert(words, out var parsedValue, out var unrecognizedNumber))
        {
            throw new FormatException($"Unrecognized decimal number word: {unrecognizedNumber}");
        }

        return parsedValue;
    }

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

    /// <inheritdoc />
    public bool TryConvert(string words, out decimal parsedValue, out string? unrecognizedNumber)
    {
        parsedValue = default;
        unrecognizedNumber = words ?? string.Empty;

        if (words is null || string.IsNullOrWhiteSpace(words))
        {
            return false;

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Use TryToDecimalNumber(words, out var d, culture, out var bad) and branch on the boolean return.
  2. Use the reported unrecognized token to locate the malformed fragment.
  3. Verify the integer part parses with TryToNumber for that culture and that fractional digit count is within 1-28.
  4. Confirm the phrase uses exactly one decimal marker and a supported negative affix.

Example fix

// before
var d = "two point banana".ToDecimalNumber(CultureInfo.GetCultureInfo("en"));
// after
if ("two point banana".TryToDecimalNumber(out var d, CultureInfo.GetCultureInfo("en"), out var bad))
    Console.WriteLine(d);
else
    Console.WriteLine($"unrecognized: {bad}");
Defensive patterns

Strategy: validation

Validate before calling

// Use the non-throwing decimal overload; it reports the bad token.
if (!words.TryToDecimalNumber(out var d, culture, out var unrecognized))
    return Result.Fail($"unrecognized decimal token: {unrecognized}");
return Result.Ok(d);

Try / catch

try { var d = words.ToDecimalNumber(culture); }
catch (FormatException ex) when (ex.Message.StartsWith("Unrecognized decimal number word"))
    { /* malformed decimal phrase */ }

Prevention

When it happens

Trigger: Calling ToDecimalNumber(words, culture) with a malformed decimal phrase: more than 28 fractional digits, an unrecognized fractional digit word, a missing/extra decimal marker, a value outside decimal range, or an unrecognized integer part for the locale's grammar.

Common situations: Free-form user text fed to ToDecimalNumber; locale mismatch; phrases with unsupported negative affixes; fractional runs longer than decimal's 28-29 significant digits; English scale overflow that still fits no decimal.

Related errors


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