Humanizr/Humanizer · error · InvalidOperationException
Case-aware citation phrases for '{catalog.LocaleCode}' requi
Error message
Case-aware citation phrases for '{catalog.LocaleCode}' require the duration phrase surface. What it means
Thrown by ValidateCitationBaseDurationForms when a locale has a case-aware authored citation case (the citation realization kind is Authored with no authored units) but the top-level 'phrases' section passed to the parser is null. The citation case then has no duration phrase surface to fall back on, so the generator cannot resolve base-duration forms.
Source
Thrown at src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs:903
$"Case overlay '{path}.multiple.forms' must explicitly define reachable '{requiredForm}' form.");
}
}
static void ValidateCitationBaseDurationForms(
DurationCaseCatalog catalog,
SimpleYamlValue? phrasesValue,
ImmutableArray<string> requiredMultipleForms)
{
if (!catalog.Realizations.TryGetValue(catalog.CitationCase, out var citation) ||
citation.Kind != DurationCaseRealizationKind.Authored ||
citation.Units.Count != 0)
{
return;
}
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(View on GitHub (pinned to ffc2b77c0f)
Solutions
- Ensure the locale YAML includes a 'phrases' section with at least a 'duration' sub-mapping.
- Pass the phrases value to DurationCaseNormalization.Parse via the phrases parameter so the citation case can validate its base-duration forms.
- If the locale genuinely has no duration phrases, mark the citation case as notApplicable or unsupported instead of authored.
Example fix
# before — locale file has durationCases but no phrases
phrases: ~
durationCases:
...
# after
phrases:
duration:
second:
...
durationCases:
... Defensive patterns
Strategy: validation
Validate before calling
# Verify the locale file has a non-null 'phrases' section when durationCases is present
# python: if 'durationCases' in yaml and not yaml.get('phrases'): print('MISSING phrases') Prevention
- Ensure every locale YAML that declares durationCases also includes a phrases.duration section.
- When splitting locale data across files, pass the phrases reference to the parser.
- If the locale has no duration phrases at all, mark the citation case as notApplicable instead of authored.
When it happens
Trigger: The locale YAML defines durationCases with an authored citation case (units count is 0) but does not provide a 'phrases' block at all, so phrasesValue is null when DurationCaseNormalization.Parse is called.
Common situations: A locale declares a durationCases structure with a citation case that relies on the base phrases.duration surface, but the locale file (or the caller) omits the phrases section entirely. This typically happens when a contributor splits durationCases into a separate file or partial and forgets to pass the phrases reference.
Related errors
- Case-aware citation phrases for '{catalog.LocaleCode}' requi
- Case-aware citation phrases for '{catalog.LocaleCode}' requi
- '{path}' must define exactly one of phrase, sameRenderedAs,
- Case overlay '{path}.phrase' must explicitly define singular
- Duration case phrases use unsupported plural rule '{pluralRu
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/62620e8264f22c6d.
Report an issue: GitHub.