Humanizr/Humanizer · error · InvalidOperationException

Case-aware citation phrases for '{catalog.LocaleCode}' requi

Error message

Case-aware citation phrases for '{catalog.LocaleCode}' require '{path}.{unitName}'.

What it means

Thrown by ValidateCitationBaseDurationForms during iteration over TimeUnits when the phrases.duration mapping is missing one of the eight required time units (millisecond, second, minute, hour, day, week, month, year). The validator checks each unit name with TryGetValue and throws on the first absence.

Source

Thrown at src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs:917

            }

            var path = $"{catalog.LocaleCode}.phrases.duration";
            var phrases = phrasesValue is null
                ? throw new InvalidOperationException(
                    $"Case-aware citation phrases for '{catalog.LocaleCode}' require the duration phrase surface.")
                : ExpectMapping(phrasesValue, $"{catalog.LocaleCode}.phrases");
            if (!phrases.TryGetValue("duration", out var durationValue))
            {
                throw new InvalidOperationException(
                    $"Case-aware citation phrases for '{catalog.LocaleCode}' require '{path}'.");
            }

            var duration = ExpectMapping(durationValue, path);
            foreach (var unitName in TimeUnits)
            {
                if (!duration.TryGetValue(unitName, out var phraseValue))
                {
                    throw new InvalidOperationException(
                        $"Case-aware citation phrases for '{catalog.LocaleCode}' require '{path}.{unitName}'.");
                }

                ValidateReachableMultipleForms(
                    phraseValue,
                    $"{path}.{unitName}",
                    requiredMultipleForms);
            }
        }

        static ImmutableDictionary<string, DurationCaseOverlay> ResolveCases(
            ImmutableArray<string> inventory,
            ImmutableDictionary<string, DurationCaseRealization> realizations,
            string path)
        {
            var cases = ImmutableDictionary.CreateBuilder<string, DurationCaseOverlay>(StringComparer.Ordinal);
            foreach (var caseName in inventory)
            {

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Compare the keys in phrases.duration against the full TimeUnits list: millisecond, second, minute, hour, day, week, month, year.
  2. Add the missing unit(s) with appropriate singular/multiple forms for the locale.
  3. Rebuild to confirm all eight units are present.

Example fix

# before (missing 'week', 'month', 'year')
duration:
  millisecond: ...
  second: ...
  minute: ...
  hour: ...
  day: ...
# after
duration:
  millisecond: ...
  second: ...
  minute: ...
  hour: ...
  day: ...
  week: ...
  month: ...
  year: ...
Defensive patterns

Strategy: validation

Validate before calling

# Verify all 8 time units exist in phrases.duration
$required = @('millisecond','second','minute','hour','day','week','month','year')
# python: for u in required: assert u in yaml['phrases']['duration'], f'missing {u}'

Prevention

When it happens

Trigger: The phrases.duration mapping exists but omits one or more of the eight standard time units required by the TimeUnits array.

Common situations: A contributor adds phrases.duration for the common units (second, minute, hour, day) but forgets the less frequently used ones (millisecond, week, month, year), or removes a unit thinking it is optional.

Related errors


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