Humanizr/Humanizer · error · InvalidOperationException

Inflection rule '{id}' scope uses a script not declared by i

Error message

Inflection rule '{id}' scope uses a script not declared by its owner.

What it means

A rule's 'scope.scripts' entries must all appear in the bundle's top-level 'scripts:' list. ParseRules throws when a rule references a Unicode script the owner has not declared, because a rule cannot operate on a script its bundle does not own.

Source

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

                var countabilities = GetRequiredStrings(
                    scope,
                    "countability",
                    $"Inflection rule '{id}' scope must define countability");
                foreach (var countability in countabilities)
                {
                    if (!Countabilities.Contains(countability))
                    {
                        throw new InvalidOperationException(
                            $"Inflection rule '{id}' scope countability '{countability}' is unsupported.");
                    }
                }
                var ruleScripts = GetRequiredStrings(
                    scope,
                    "scripts",
                    $"Inflection rule '{id}' scope must define scripts");
                if (ruleScripts.Any(script => !ownerScripts.Contains(script, StringComparer.Ordinal)))
                {
                    throw new InvalidOperationException(
                        $"Inflection rule '{id}' scope uses a script not declared by its owner.");
                }

                var match = GetRequiredMapping(rule, "match", $"Inflection rule '{id}' must define match");
                ValidateProperties(
                    match,
                    $"Inflection rule '{id}' match",
                    "prefix", "suffix", "precedingNot", "preceding-not");
                var prefix = NormalizeAuthoredText(
                    match.GetScalar("prefix") ?? string.Empty,
                    casing,
                    ruleScripts,
                    $"rule '{id}' prefix",
                    allowStemPlaceholder: false,
                    allowNonLetters: false);
                var suffix = NormalizeAuthoredText(
                    match.GetScalar("suffix") ?? string.Empty,
                    casing,

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Add the script to the top-level 'scripts:' list of the inflection bundle
  2. Remove the script from the rule's 'scope.scripts'

Example fix

# before
    scripts:
      - 'Latn'
    rules:
      - id: 'zz.forward.consonant-y'
        scope:
          scripts:
            - 'Cyrl'
# after
    scripts:
      - 'Latn'
      - 'Cyrl'
Defensive patterns

Strategy: validation

Validate before calling

var ownerScripts = GetRequiredStrings(m, "scripts");
foreach (var rule in rules)
foreach (var s in rule.Scope.Scripts)
    if (!ownerScripts.Contains(s, StringComparer.Ordinal))
        Report($"{locale}: rule '{rule.Id}' script '{s}' not declared by owner.");

Type guard

static bool RuleScriptsDeclaredByOwner(
    ImmutableArray<string> ownerScripts, IEnumerable<string> ruleScripts) =>
    ruleScripts.All(s => ownerScripts.Contains(s, StringComparer.Ordinal));

Prevention

When it happens

Trigger: A rule scope lists e.g. 'Cyrl' while the bundle's top-level 'scripts:' only declares 'Latn'.

Common situations: Adding a script-specific rule without adding the script to the owner declaration; authoring a multi-script locale and scoping rules narrowly.

Related errors


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