Humanizr/Humanizer · critical · InvalidOperationException
Locale '{localeCode}.{path}.{key}' must be a non-empty strin
Error message
Locale '{localeCode}.{path}.{key}' must be a non-empty string. Omit unused sparse slots instead. What it means
Thrown by ValidateMinuteWordValue when a clock minute slot value is a string but empty, with allowEmpty:false. The canonical schema expects unused sparse slots to be omitted entirely rather than present-but-empty, so that minute tables stay dense and unambiguous.
Source
Thrown at src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs:357
return new SimpleYamlMapping(normalizedValues.ToImmutable());
}
static void ValidateMinuteWordValue(
string localeCode,
string path,
string key,
SimpleYamlValue value,
bool allowEmpty)
{
if (value is not SimpleYamlScalar scalar || !scalar.IsString)
{
throw new InvalidOperationException(
$"Locale '{localeCode}.{path}.{key}' must be a string.");
}
if (!allowEmpty && string.IsNullOrEmpty(scalar.Value))
{
throw new InvalidOperationException(
$"Locale '{localeCode}.{path}.{key}' must be a non-empty string. Omit unused sparse slots instead.");
}
}
static void ValidateNumberFormattingBlock(string localeCode, SimpleYamlMapping formatting)
{
foreach (var property in formatting.Values.Keys.Where(static property => property is not ("decimalSeparator" or "negativeSign" or "groupSeparator")))
{
throw new InvalidOperationException(
$"Locale '{localeCode}.surfaces.number.formatting' defines unsupported property '{property}'. Supported properties: decimalSeparator, negativeSign, groupSeparator.");
}
ValidateOptionalFormattingProperty(localeCode, formatting, "decimalSeparator");
ValidateOptionalFormattingProperty(localeCode, formatting, "negativeSign");
ValidateOptionalFormattingProperty(localeCode, formatting, "groupSeparator");
if (formatting.Values.Count == 0)
{View on GitHub (pinned to ffc2b77c0f)
Solutions
- Delete the empty minute entry entirely from surfaces.clock.minutes (the table is sparse by design).
- If the minute genuinely needs a word, fill in a non-empty localized string.
- Rebuild to confirm the locale compiles.
Example fix
# before minutes: 5: 6: six minutes # after minutes: 6: six minutes
Defensive patterns
Strategy: validation
Validate before calling
# Detect empty minute values before building: # (YAML lint) ensure no 'minutes:' child is blank. # Quick PowerShell over the locale file: Select-String -Path src/Humanizer/Locales/<code>.yml -Pattern '^\s*\d+:\s*$'
Prevention
- Delete unused minute slots rather than leaving them empty.
- Treat the minutes table as sparse: only include slots that have a real translation.
- Run 'dotnet build' after edits to surface the offending {key}.
When it happens
Trigger: A locale YAML minute entry is written as '5:' or '5: ""' (empty value). NormalizeMinuteWordsMapping calls ValidateMinuteWordValue with allowEmpty:false for clock minutes, hitting CanonicalLocaleAuthoring.cs:355-359.
Common situations: Clearing a value while editing instead of deleting the key; copying a template that left placeholder empty strings; a merge tool留下ing blank lines for removed translations.
Related errors
- Locale '{localeCode}.{path}' defines duplicate numeric minut
- Locale '{localeCode}.{path}.{key}' must be a string.
- Locale '{localeCode}.surfaces.number.formatting' defines uns
- Locale '{localeCode}.surfaces.number.formatting' must define
- Locale '{localeCode}.surfaces.number.formatting.{propertyNam
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/97ced1cd9a45f297.
Report an issue: GitHub.