Humanizr/Humanizer · error · InvalidOperationException
Case overlay '{path}' must explicitly define singular and nu
Error message
Case overlay '{path}' must explicitly define singular and numeric multiple forms. What it means
After sameAsNominative/unsupported checks, ParseUnit (DurationCaseModels.cs:1178-1184) parses the unit as a TimeSpan phrase via LocalePhraseNormalization.ParseTimeSpanPhrase and requires both phrase.Single and phrase.Multiple?.Forms to be non-null. A phrase unit missing its singular form or its numeric multiple forms is rejected so generated code always has both.
Source
Thrown at src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs:1182
return new DurationCaseUnit(DurationCaseUnitKind.SameAsNominative, null);
}
if (mapping.GetScalar("unsupported") is { } unsupported)
{
RejectUnknownKeys(mapping, path, ["unsupported"]);
if (!bool.TryParse(unsupported, out var enabled) || !enabled)
{
throw new InvalidOperationException($"'{path}.unsupported' must be true.");
}
return new DurationCaseUnit(DurationCaseUnitKind.Unsupported, null);
}
var phrase = LocalePhraseNormalization.ParseTimeSpanPhrase(value, path);
if (phrase.Single is null ||
phrase.Multiple?.Forms is null)
{
throw new InvalidOperationException(
$"Case overlay '{path}' must explicitly define singular and numeric multiple forms.");
}
return new DurationCaseUnit(DurationCaseUnitKind.Phrase, phrase);
}
static bool ContainsInheritanceMarker(SimpleYamlValue value) =>
value switch
{
SimpleYamlScalar scalar => scalar.Value.Contains("↑↑↑", StringComparison.Ordinal),
SimpleYamlMapping mapping => mapping.Values.Values.Any(ContainsInheritanceMarker),
SimpleYamlSequence sequence => sequence.Items.Any(ContainsInheritanceMarker),
_ => false
};
static SimpleYamlMapping ExpectMapping(SimpleYamlValue value, string path) =>
value as SimpleYamlMapping
?? throw new InvalidOperationException($"'{path}' must be a mapping.");View on GitHub (pinned to ffc2b77c0f)
Solutions
- Add the missing half: ensure phrase.single (with numeric/words) AND phrase.multiple.forms (default/singular/etc.) both exist.
- If only the singular exists and no plural is needed, still provide a multiple.forms entry (often mirroring the singular).
- If the unit should not have a phrase, switch it to sameAsNominative: true or unsupported: true.
Example fix
# before - multiple missing forms
second:
phrase:
single: { numeric: '1 sekunda', words: 'jedna sekunda' }
multiple: {}
# after
second:
phrase:
single: { numeric: '1 sekunda', words: 'jedna sekunda' }
multiple:
forms: { default: 'sekund', singular: 'sekundy', plural: 'sekund' } Defensive patterns
Strategy: validation
Validate before calling
# A phrase unit must define single and multiple.forms
foreach ($u in $caseUnits.GetEnumerator()) {
$v = $u.Value
if ($v -is [hashtable] -and $v.ContainsKey('phrase')) {
$p = $v.phrase
if (-not $p.single -or -not $p.multiple -or -not $p.multiple.forms) {
throw "unit '$($u.Key)' phrase must define single and multiple.forms"
}
}
} Prevention
- Always author phrase blocks with both single: (numeric/words) and multiple:forms:.
- Copy a complete phrase block from a sibling unit as a template.
- If a phrase is not appropriate, use sameAsNominative or unsupported instead.
When it happens
Trigger: A unit's phrase: block has single: but no multiple: (or multiple: without forms:), or vice-versa.
Common situations: Incomplete phrase authoring; copying a phrase block from a locale whose multiple-form shape differs; forgetting the forms: level under multiple:.
Related errors
- '{path}.units' must explicitly define '{unitName}'.
- '{path}.sameAsNominative' must be true.
- '{path}.unsupported' must be true.
- '{path}' must be a mapping.
- '{path}' defines unsupported property '{key}'. Supported pro
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/ef76275df29fa3ff.
Report an issue: GitHub.