Humanizr/Humanizer · error · InvalidOperationException
Locale '{localeCode}' must define required top-level propert
Error message
Locale '{localeCode}' must define required top-level property 'surfaces'. What it means
A base locale (no variantOf) must define `surfaces:` (CanonicalLocaleAuthoring.cs:89-96). Only a pure variant — one declaring `variantOf:` — may omit surfaces and inherit everything. This prevents a culture being registered with no localizable content.
Source
Thrown at src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs:94
var declaredLocale = root.GetScalar("locale")
?? throw new InvalidOperationException(
$"Locale '{localeCode}' must define required top-level property 'locale'.");
if (!string.Equals(localeCode, declaredLocale, StringComparison.Ordinal))
{
throw new InvalidOperationException(
$"Locale '{declaredLocale}' must match file locale '{localeCode}'.");
}
var variantOf = root.GetScalar("variantOf");
SimpleYamlMapping surfaces;
if (!root.TryGetValue("surfaces", out var surfacesValue))
{
if (string.IsNullOrWhiteSpace(variantOf))
{
throw new InvalidOperationException(
$"Locale '{localeCode}' must define required top-level property 'surfaces'.");
}
surfaces = new SimpleYamlMapping(
ImmutableDictionary<string, SimpleYamlValue>.Empty.WithComparers(StringComparer.Ordinal));
}
else
{
surfaces = surfacesValue is SimpleYamlMapping surfacesMapping
? surfacesMapping
: throw new InvalidOperationException($"Locale '{localeCode}.surfaces' must be a mapping.");
}
foreach (var surface in surfaces.Values)
{
if (!SupportedSurfaceNames.Contains(surface.Key, StringComparer.Ordinal))
{
throw new InvalidOperationException(View on GitHub (pinned to ffc2b77c0f)
Solutions
- Add a `surfaces:` mapping (even `surfaces: {}` is valid for a first stub) if the locale is standalone.
- If the locale only overrides a parent, add `variantOf: "<parent>"` and omit surfaces.
- Move any surface content you removed back under surfaces.
Example fix
# before (standalone locale)
locale: "de"
# after
locale: "de"
surfaces:
clock: {} Defensive patterns
Strategy: validation
Validate before calling
import yaml, sys
doc = yaml.safe_load(open(sys.argv[1], encoding='utf-8'))
is_variant = bool(doc.get('variantOf'))
assert is_variant or 'surfaces' in doc, 'a non-variant locale must define surfaces:' Prevention
- Author locales against the canonical schema; the error message lists the exact allowed names.
- Run `dotnet build src/Humanizer/Humanizer.csproj` locally so the generator reports locale errors before push.
- Copy an existing compliant locale file as your template rather than writing YAML from scratch.
When it happens
Trigger: A new top-level locale file has `locale:` but no `surfaces:` block and no `variantOf:`.
Common situations: Starting a brand-new locale and forgetting the surfaces block; stripping content during a refactor.
Related errors
- Locale '{localeCode}' defines unsupported top-level property
- Locale '{localeCode}' must define required top-level propert
- Locale '{declaredLocale}' must match file locale '{localeCod
- Locale '{localeCode}.surfaces' must be a mapping.
- Locale '{localeCode}.surfaces' defines unsupported surface '
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/56e50dafad419cfb.
Report an issue: GitHub.