Humanizr/Humanizer · error · InvalidOperationException
Locale '{localeCode}.headings' must define '{key}'.
Error message
Locale '{localeCode}.headings' must define '{key}'. What it means
The headings schema requires both 'full' and 'short' sub-keys. ParseHeadingSequence is called for each expected key, and if the key is absent from the mapping the generator cannot produce a complete heading set, so it fails fast.
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocaleYamlCatalog.cs:835
: formattingValue as SimpleYamlMapping
?? throw new InvalidOperationException($"Locale '{localeCode}.numberFormatting' must be a mapping.");
}
static SimpleYamlMapping? ResolveInflection(
string localeCode,
ImmutableDictionary<string, SimpleYamlValue> features)
{
return !features.TryGetValue("inflection", out var inflectionValue)
? null
: inflectionValue as SimpleYamlMapping
?? throw new InvalidOperationException($"Locale '{localeCode}.inflection' must be a mapping.");
}
static ImmutableArray<string> ParseHeadingSequence(SimpleYamlMapping mapping, string key, string localeCode)
{
if (!mapping.TryGetValue(key, out var headingValue))
{
throw new InvalidOperationException($"Locale '{localeCode}.headings' must define '{key}'.");
}
if (headingValue is not SimpleYamlSequence sequence)
{
throw new InvalidOperationException($"Locale '{localeCode}.headings.{key}' must be a sequence.");
}
if (sequence.Items.Length != 16)
{
throw new InvalidOperationException($"Locale '{localeCode}.headings.{key}' must contain exactly 16 entries.");
}
var headings = ImmutableArray.CreateBuilder<string>(16);
for (var index = 0; index < sequence.Items.Length; index++)
{
if (sequence.Items[index] is not SimpleYamlScalar scalar)
{
throw new InvalidOperationException($"Locale '{localeCode}.headings.{key}[{index}]' must be a scalar.");View on GitHub (pinned to ffc2b77c0f)
Solutions
- Add the missing key named in the error message to the headings mapping.
- Ensure both 'full:' and 'short:' are present, each with a 16-entry sequence.
- If unsure of short forms, duplicate the full forms as a starting point and abbreviate afterward.
Example fix
# before — missing 'short'
headings:
full:
- January
# after
headings:
full:
- January
short:
- Jan 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 isinstance(data.get('headings'), dict):
for key in ('full', 'short'):
if key not in data['headings']:
print(f'{f.name}: headings must define "{key}"') Prevention
- Always provide both 'full' and 'short' under headings — neither is optional.
- When adding headings for the first time, copy both blocks from a reference locale.
- Add a lint that flags headings mappings missing either required key.
When it happens
Trigger: A locale's 'headings:' mapping defines 'full:' but omits 'short:', or vice versa. The {key} placeholder in the message names the missing property.
Common situations: Authoring partial heading data; copy-pasting from a locale that only had one variant; deleting a block during cleanup.
Related errors
- Locale '{localeCode}.headings' must be a mapping.
- Locale '{localeCode}.headings' defines unsupported property
- Locale '{localeCode}.headings.{key}' must be a sequence.
- Locale '{localeCode}.headings.{key}' must contain exactly 16
- Locale '{localeCode}.headings.{key}[{index}]' must be a scal
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/3db6720023f81ec8.
Report an issue: GitHub.