Humanizr/Humanizer · error · InvalidOperationException

Inflection rule '{ruleId}' output must contain exactly one b

Error message

Inflection rule '{ruleId}' output must contain exactly one bounded '{stem}' placeholder.

What it means

Every inflection rule output template must contain exactly one '{stem}' placeholder, bounded by curly braces, with no additional unbounded braces elsewhere. The generator uses this placeholder to splice the lexeme stem into the inflected form at code-generation time, so the template grammar must be unambiguous.

Source

Thrown at src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/InflectionCatalogValidation.cs:146

                         string.IsNullOrWhiteSpace(optionalScalar.Value)))
                    {
                        throw new InvalidOperationException(
                            $"Inflection source '{entry.Key}' {optionalProperty} must be a non-empty scalar.");
                    }
                }
            }
        }

        static void ValidateTemplate(string ruleId, string template)
        {
            var marker = template.IndexOf("{stem}", StringComparison.Ordinal);
            var remainder = template.Replace("{stem}", string.Empty);
            if (marker < 0 ||
                template.IndexOf("{stem}", marker + "{stem}".Length, StringComparison.Ordinal) >= 0 ||
                remainder.Contains('{') ||
                remainder.Contains('}'))
            {
                throw new InvalidOperationException(
                    $"Inflection rule '{ruleId}' output must contain exactly one bounded '{{stem}}' placeholder.");
            }
        }

        static void ValidateInvariantCapability(
            string capability,
            string casing,
            ImmutableArray<InflectionLexemeInput> lexemes,
            ImmutableArray<InflectionRuleInput> rules)
        {
            if (capability != "invariant")
            {
                return;
            }

            if (!rules.IsEmpty)
            {
                throw new InvalidOperationException(

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Ensure the template contains exactly one '{stem}' placeholder and no other curly braces.
  2. If the output must contain literal braces, escape or restructure the rule so braces only appear around 'stem'.
  3. Remove duplicate '{stem}' occurrences — a rule applies one suffix/prefix transformation per stem.

Example fix

# before
rules:
  - id: 'plural-es'
    output: '{stem}{stem}s'
# after
rules:
  - id: 'plural-es'
    output: '{stem}s'
Defensive patterns

Strategy: validation

Validate before calling

# Before building, verify each rule output template has exactly one {stem} and no stray braces.
python3 -c "
import yaml, sys
for f in sys.argv[1:]:
    d = yaml.safe_load(open(f))
    owners = (d.get('inflection',{}).get('owners') or [])
    for owner in owners:
        for rule in (owner.get('rules') or []):
            tpl = rule.get('output','')
            remainder = tpl.replace('{stem}', '')
            if tpl.count('{stem}') != 1 or '{' in remainder or '}' in remainder:
                print(f'{f}: rule {rule.get("id","")!r} template invalid: {tpl!r}')
" src/Humanizer/Locales/*.yml

Prevention

When it happens

Trigger: ValidateTemplate is called with a template string that either contains zero '{stem}' markers, contains two or more, or contains stray '{' or '}' characters outside the placeholder. For example, 'prefix{stem}suffix{stem}' or 'output{stem}extra}'.

Common situations: Writing an inflection rule template with a typo like '{stme}' instead of '{stem}'. Accidentally including literal braces in the output form. Forgetting the placeholder entirely in a rule that needs stem substitution.

Related errors


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