Humanizr/Humanizer · error · InvalidOperationException

Locale '{localeCode}.surfaces' defines unsupported surface '

Error message

Locale '{localeCode}.surfaces' defines unsupported surface '{surface.Key}'. Supported surfaces: {string.Join(", ", SupportedSurfaceNames)}.

What it means

Each key under `surfaces:` must be one of the supported surface names: list, formatter, durationCases, phrases, number, ordinal, clock, compass, calendar, inflection (CanonicalLocaleAuthoring.cs:108-115). Unknown surface keys are rejected so contributors don't add content the generator ignores.

Source

Thrown at src/Humanizer.SourceGenerators/Common/CanonicalLocaleAuthoring.cs:112

                    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(
                        $"Locale '{localeCode}.surfaces' defines unsupported surface '{surface.Key}'. " +
                        $"Supported surfaces: {string.Join(", ", SupportedSurfaceNames)}.");
                }

                if (surface.Value is not SimpleYamlMapping)
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.surfaces.{surface.Key}' must be a mapping.");
                }

                RejectExplicitDefaultEngines(localeCode, $"surfaces.{surface.Key}", surface.Value);
            }

            return new CanonicalLocaleDocument(
                localeCode,
                variantOf,
                surfaces,
                NormalizeCanonicalText(fileText));

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Rename the key to a supported surface name from the list in the message.
  2. For number content use surfaces.number.words / .parse / .formatting rather than a top-level numberToWords.
  3. Remove the surface if it was added by mistake.

Example fix

# before
surfaces:
  cloc: {}
# after
surfaces:
  clock: {}
Defensive patterns

Strategy: validation

Validate before calling

import yaml, sys
ALLOWED = {'list','formatter','durationCases','phrases','number','ordinal','clock','compass','calendar','inflection'}
doc = yaml.safe_load(open(sys.argv[1], encoding='utf-8'))
if isinstance(doc.get('surfaces'), dict):
    bad = [k for k in doc['surfaces'] if k not in ALLOWED]
    assert not bad, f'unsupported surfaces: {bad}'

Prevention

When it happens

Trigger: A surface key typo (cloc, calender), or a legacy flat name placed under surfaces (e.g. surfaces.numberToWords instead of surfaces.number.words).

Common situations: Renaming/migrating a locale and putting the old property name under surfaces; spelling mistakes.

Related errors


AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13). Data as JSON: /api/errors/fe984e350fb79227. Report an issue: GitHub.