Humanizr/Humanizer · error · InvalidOperationException

Locale '{localeCode}.surfaces' must be a mapping.

Error message

Locale '{localeCode}.surfaces' must be a mapping.

What it means

`surfaces:` must be a YAML mapping (CanonicalLocaleAuthoring.cs:103-105). A scalar or sequence here cannot hold named surfaces, so the generator rejects it.

Source

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

            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(
                        $"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);

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Make surfaces a mapping: `surfaces:` followed by indented `key:` blocks.
  2. For an empty stub use `surfaces: {}` (flow mapping).
  3. Re-run the build.

Example fix

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

Strategy: validation

Validate before calling

import yaml, sys
doc = yaml.safe_load(open(sys.argv[1], encoding='utf-8'))
if 'surfaces' in doc:
    assert isinstance(doc['surfaces'], dict), 'surfaces: must be a mapping'

Prevention

When it happens

Trigger: `surfaces: en` or `surfaces: [clock, number]` instead of a keyed mapping; a stray `:` placement turning it into a scalar.

Common situations: Hand-typing the surfaces line; bad copy-paste from a list.

Related errors


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