Humanizr/Humanizer · error · InvalidOperationException

Duplicate inflection lexeme id '{id}'.

Error message

Duplicate inflection lexeme id '{id}'.

What it means

Lexeme ids must be unique within a locale (ordinal string comparison). ParseLexemes tracks ids in a HashSet and throws when 'ids.Add(id)' returns false, because the inflection catalog keys lexemes by id.

Source

Thrown at src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/InflectionCatalogParsing.cs:257

            }

            var ids = new HashSet<string>(StringComparer.Ordinal);
            var lexemes = ImmutableArray.CreateBuilder<InflectionLexemeInput>();
            foreach (var value in lexemeSequence.Items)
            {
                if (value is not SimpleYamlMapping lexeme)
                {
                    throw new InvalidOperationException("Inflection lexemes must be mappings.");
                }

                ValidateProperties(
                    lexeme,
                    "Inflection lexeme",
                    "id", "pos", "countability", "sense", "forms", "sources");
                var id = GetRequiredScalar(lexeme, "id", "Inflection lexeme must define id");
                if (!ids.Add(id))
                {
                    throw new InvalidOperationException($"Duplicate inflection lexeme id '{id}'.");
                }

                if (GetRequiredScalar(lexeme, "pos", $"Inflection lexeme '{id}' must define pos") != "noun")
                {
                    throw new InvalidOperationException($"Inflection lexeme '{id}' pos must be 'noun'.");
                }

                var countability = GetRequiredScalar(
                    lexeme,
                    "countability",
                    $"Inflection lexeme '{id}' must define countability");
                if (!Countabilities.Contains(countability))
                {
                    throw new InvalidOperationException(
                        $"Inflection lexeme '{id}' countability '{countability}' is unsupported.");
                }

                string? sense = null;

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Give each lexeme a distinct id (e.g. suffix by sense or part of speech)

Example fix

# before
      - id: 'zz.noun.cat'
        ...
      - id: 'zz.noun.cat'
        sense: 'animal'
# after
      - id: 'zz.noun.cat'
        ...
      - id: 'zz.noun.cat.animal'
        sense: 'animal'
Defensive patterns

Strategy: validation

Validate before calling

var ids = new HashSet<string>(StringComparer.Ordinal);
foreach (var lexeme in lexemes)
    if (!ids.Add(lexeme.Id))
        Report($"{locale}: duplicate lexeme id '{lexeme.Id}'.");

Type guard

static bool LexemeIdsUnique(IEnumerable<Lexeme> lexemes) =>
    lexemes.Select(l => l.Id).Distinct(StringComparer.Ordinal).Count() == lexemes.Count();

Prevention

When it happens

Trigger: Two entries under 'lexemes:' share the same 'id:' value (exact or case-differing).

Common situations: Copy-pasting a lexeme block to add a sense variant and forgetting to rename the id; case collisions from a casing-mode change.

Related errors


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