Humanizr/Humanizer · error · InvalidOperationException
Locale '{localeCode}.phrases' must be a mapping.
Error message
Locale '{localeCode}.phrases' must be a mapping. What it means
The 'phrases' feature holds localized phrase templates as a mapping keyed by phrase identifier. Only a YAML mapping is valid here; a scalar or sequence cannot represent keyed phrase entries, so the phrase catalog resolver throws.
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs:773
? null
: grammarValue as SimpleYamlMapping
?? throw new InvalidOperationException($"Locale '{localeCode}.grammar' must be a mapping.");
}
static LocalePhraseCatalog? ResolvePhraseCatalog(
string localeCode,
ImmutableDictionary<string, SimpleYamlValue> features)
{
var preserveDurationCaseForms =
features.TryGetValue("formatter", out var formatterValue) &&
formatterValue is SimpleYamlMapping formatter &&
formatter.GetScalar("casePluralRule") is not null;
return !features.TryGetValue("phrases", out var phraseValue)
? null
: phraseValue is SimpleYamlMapping mapping
? LocalePhraseNormalization.Create(localeCode, mapping, preserveDurationCaseForms)
: throw new InvalidOperationException($"Locale '{localeCode}.phrases' must be a mapping.");
}
static HeadingSet? ResolveHeadings(
string localeCode,
ImmutableDictionary<string, SimpleYamlValue> features)
{
if (!features.TryGetValue("headings", out var headingValue))
{
return null;
}
if (headingValue is not SimpleYamlMapping mapping)
{
throw new InvalidOperationException($"Locale '{localeCode}.headings' must be a mapping.");
}
foreach (var property in mapping.Values.Keys.Where(static property => property is not ("full" or "short")))
{View on GitHub (pinned to ffc2b77c0f)
Solutions
- Restructure the 'phrases:' value as a mapping where each key is a phrase identifier and each value is the localized template.
- Remove the 'phrases:' key if the locale has no phrase data.
- Validate indentation so phrase entries nest under the mapping, not as list items.
Example fix
# before phrases: - Hello # after phrases: greeting: Hello
Defensive patterns
Strategy: validation
Validate before calling
import yaml, pathlib
locales_dir = pathlib.Path('src/Humanizer/Locales')
for f in locales_dir.rglob('*.yml'):
data = yaml.safe_load(f.read_text())
if isinstance(data, dict) and 'phrases' in data:
if not isinstance(data['phrases'], dict):
print(f'{f.name}: phrases must be a mapping, got {type(data["phrases"]).__name__}') Prevention
- Structure phrases as key-value pairs, never as a flat list.
- Remove the phrases key if the locale has no phrase templates.
- Validate indentation so phrase entries are mapping children, not sequence items.
When it happens
Trigger: A locale file provides 'phrases:' as a scalar string or as a YAML sequence rather than a mapping of phrase-key to content.
Common situations: Editing phrase data and accidentally flattening the structure; misindenting phrase entries so they parse as a sequence; leaving a placeholder scalar.
Related errors
- Phrase section '{path}' must be a mapping.
- Phrase section '{path}' defines unsupported property '{key}'
- Phrase '{path}' must define forms, 'symbol', or 'template'.
- Phrase '{path}' must define forms.
- Phrase '{path}' must define 'numeric', 'text', or 'words'.
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/ce99f56f21ac303f.
Report an issue: GitHub.