Humanizr/Humanizer · error · ArgumentException

Acronym must contain only letters.

Error message

Acronym must contain only letters.

What it means

Thrown by Vocabulary.AddAcronym when the acronym string is null (caught first by ArgumentNullException), empty, or contains any non-letter character. The method requires a pure sequence of Unicode letters (char.IsLetter) so that the acronym can be wrapped in word-boundary regex and matched case-insensitively. The exception is an ArgumentException named 'acronym'.

Source

Thrown at src/Humanizer/Inflections/Vocabulary.cs:43

    private static Regex LetterSRegex() => LetterSRegexGenerated();
#else
    private static readonly Regex LetterSRegexField = new(LetterSPattern, RegexOptions.Compiled);

    private static Regex LetterSRegex() => LetterSRegexField;
#endif

    /// <summary>
    /// Adds an acronym whose casing should be preserved when humanizing strings.
    /// </summary>
    /// <param name="acronym">The letters in the acronym's canonical output casing, e.g. "HTML".</param>
    /// <exception cref="ArgumentNullException"><paramref name="acronym"/> is null.</exception>
    /// <exception cref="ArgumentException"><paramref name="acronym"/> is empty or contains a non-letter.</exception>
    public void AddAcronym(string acronym)
    {
        ArgumentNullException.ThrowIfNull(acronym);
        if (acronym.Length == 0 || !acronym.All(char.IsLetter))
        {
            throw new ArgumentException("Acronym must contain only letters.", nameof(acronym));
        }

        lock (acronyms)
        {
            if (!acronyms.Any(rule => rule.IsFullMatch(acronym)))
            {
                acronyms.Add(new(
                    $@"\b{Regex.Escape(acronym)}\b",
                    acronym.Replace("$", "$$"),
                    RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled));
            }
        }
    }

    /// <summary>
    /// Adds a word to the vocabulary which cannot easily be pluralized/singularized by RegEx, e.g. "person" and "people".
    /// </summary>
    /// <param name="singular">The singular form of the irregular word, e.g. "person".</param>

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Strip non-letter characters before registering, or reject the input if it is not pure letters.
  2. For acronyms that legitimately contain digits/symbols, do not use AddAcronym; instead preprocess the source string or post-process the humanized output.
  3. Validate with acronym.All(char.IsLetter) && acronym.Length > 0 before calling AddAcronym.

Example fix

// before
Vocabularies.Default.AddAcronym("HTML5"); // throws

// after
var clean = new string("HTML5".Where(char.IsLetter).ToArray());
if (clean.Length > 0)
    Vocabularies.Default.AddAcronym(clean);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(acronym) || !acronym.All(char.IsLetter))
    throw new ArgumentException("Acronym must be non-empty letters only.", nameof(acronym));
Vocabularies.Default.AddAcronym(acronym);

Type guard

static bool IsValidAcronym(string s) => !string.IsNullOrEmpty(s) && s.All(char.IsLetter);

Try / catch

try { Vocabularies.Default.AddAcronym(acronym); }
catch (ArgumentException) { /* skip or sanitize the acronym */ }

Prevention

When it happens

Trigger: Calling Vocabularies.Default.AddAcronym("HTML5") (contains a digit); AddAcronym(""); AddAcronym("A.B"); AddAcronym("C++"). Acronyms with embedded digits, punctuation, or whitespace all fail because char.IsLetter returns false for those characters.

Common situations: Registering product/standard codes that include version numbers or symbols (e.g. 'ISO-9001', 'B2B', 'C#'); reading acronym lists from a file without sanitizing; treating a free-text label as an acronym.

Related errors


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