Humanizr/Humanizer · error · InvalidOperationException
Phrase forms '{path}' must define at least one form.
Error message
Phrase forms '{path}' must define at least one form. What it means
Thrown by ParsePhraseForms when a 'forms' mapping contains none of the recognized form keys (default, zero, singular, dual, paucal, plural, many). At least one form is required so the phrase has a fallback rendering. Surfaced as compiler diagnostic HSG003 (severity Error).
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs:384
}
static PhraseForms ParsePhraseForms(
SimpleYamlValue value,
string path,
bool preserveDuplicateForms,
params string[] allowedPlaceholders)
{
if (value is SimpleYamlScalar scalar)
{
var scalarForms = PhraseForms.FromScalar(ValidateLiteralText(path, scalar.Value, allowedPlaceholders));
return preserveDuplicateForms ? scalarForms : scalarForms.CollapseDuplicates();
}
var mapping = ExpectMapping(value, path);
RejectUnknownKeys(mapping, path, ["default", "zero", "singular", "dual", "paucal", "plural", "many"]);
if (!TryParseDirectPhraseForms(mapping, path, out var forms, allowedPlaceholders))
{
throw new InvalidOperationException($"Phrase forms '{path}' must define at least one form.");
}
return preserveDuplicateForms ? forms : forms.CollapseDuplicates();
}
static bool TryParseDirectPhraseForms(SimpleYamlMapping mapping, string path, out PhraseForms forms, params string[] allowedPlaceholders)
{
var defaultValue = GetOptionalLiteral(mapping, "default", $"{path}.default", allowedPlaceholders);
var zero = GetOptionalLiteral(mapping, "zero", $"{path}.zero", allowedPlaceholders);
var singular = GetOptionalLiteral(mapping, "singular", $"{path}.singular", allowedPlaceholders);
var dual = GetOptionalLiteral(mapping, "dual", $"{path}.dual", allowedPlaceholders);
var paucal = GetOptionalLiteral(mapping, "paucal", $"{path}.paucal", allowedPlaceholders);
var plural = GetOptionalLiteral(mapping, "plural", $"{path}.plural", allowedPlaceholders);
var many = GetOptionalLiteral(mapping, "many", $"{path}.many", allowedPlaceholders);
defaultValue ??= zero ?? singular ?? dual ?? paucal ?? plural ?? many;
if (defaultValue is null)
{View on GitHub (pinned to ffc2b77c0f)
Solutions
- Add at least one recognized form key (default, zero, singular, dual, paucal, plural, many) to the forms mapping.
- Ensure 'default' is set so all uncovered counts fall back to it.
- Rebuild to confirm the HSG003 diagnostic clears.
Example fix
# before
forms: {}
# after
forms:
default: hours
singular: hour
plural: hours Defensive patterns
Strategy: validation
Validate before calling
# A forms mapping must contain at least one of the known form keys.
known=[default zero singular dual paucal plural many]
yq -o=json '.phrases | .. | select(has("forms")) | .forms | select(tag == "!!map") | select([keys[] | select(. as $k | $known | index($k))] | length == 0)' src/Humanizer/Locales/<code>.yml Prevention
- Always set 'default' as the fallback form.
- Use the exact key names (singular, plural, etc.); avoid synonyms like 'one'.
- Build after authoring forms to catch empty/typo mappings.
When it happens
Trigger: Authoring a forms: {} empty mapping, or a forms mapping that uses only unrecognized keys (typos like 'one'/'many2' instead of singular/plural).
Common situations: Translating only some forms and accidentally deleting the default/singular key; mistyping a form key; leaving forms: as a placeholder.
Related errors
- Phrase '{path}' must define forms, 'symbol', or 'template'.
- Phrase '{path}' must define forms.
- Phrase '{path}' must define 'numeric', 'text', or 'words'.
- Phrase '{path}.countPlacement' uses unsupported count placem
- Template '{path}' must define a scalar 'value'.
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/ffd99d6edee383a7.
Report an issue: GitHub.