Humanizr/Humanizer · critical · InvalidOperationException

Locale '{localeCode}.surfaces.calendar.months' items must be

Error message

Locale '{localeCode}.surfaces.calendar.months' items must be scalar strings.

What it means

Thrown by AddCalendarFeatures when surfaces.calendar.months is a 12-element sequence but one or more items is not a YAML scalar string (e.g. a nested mapping or sequence). Month names must be plain strings so they can be emitted directly into the generated calendar table.

Source

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

        {
            foreach (var property in calendarSurface.Values.Keys.Where(static property => property is not ("months" or "monthsGenitive" or "hijriMonths")))
            {
                throw new InvalidOperationException(
                    $"Locale '{localeCode}.surfaces.calendar' defines unsupported property '{property}'. Supported properties: months, monthsGenitive, hijriMonths.");
            }

            var hasMonths = calendarSurface.TryGetValue("months", out var monthsValue);
            if (hasMonths)
            {
                if (monthsValue is not SimpleYamlSequence monthsSeq || monthsSeq.Items.Length != 12)
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.surfaces.calendar.months' must be a sequence of exactly 12 strings.");
                }

                if (monthsSeq.Items.Any(static item => item is not SimpleYamlScalar))
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.surfaces.calendar.months' items must be scalar strings.");
                }
            }

            if (calendarSurface.TryGetValue("monthsGenitive", out var monthsGenitiveValue))
            {
                if (!hasMonths)
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.surfaces.calendar.monthsGenitive' requires 'months' to also be present.");
                }

                if (monthsGenitiveValue is not SimpleYamlSequence genitiveSeq || genitiveSeq.Items.Length != 12)
                {
                    throw new InvalidOperationException(
                        $"Locale '{localeCode}.surfaces.calendar.monthsGenitive' must be a sequence of exactly 12 strings.");
                }

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Flatten every month entry to a plain scalar string in the sequence.
  2. Verify each list item is '- Janvier' style (or inline '[Janvier, ...]'), not a nested block.
  3. Rebuild to confirm the scalar-items check passes.

Example fix

# before
calendar:
  months:
    - name: Janvier
    - name: Février
# after
calendar:
  months: [Janvier, Février, Mars, Avril, Mai, Juin, Juillet, Août, Septembre, Octobre, Novembre, Décembre]
Defensive patterns

Strategy: validation

Validate before calling

# Ensure every months item is a scalar string, not a nested object.
# After parsing, assert: $months | ForEach-Object { $_ -is [string] }.

Prevention

When it happens

Trigger: A month entry is written as a nested object (e.g. '- {name: Janvier}') or a sub-list. The check monthsSeq.Items.Any(item => item is not SimpleYamlScalar) at CanonicalLocaleAuthoring.cs:466-470 fires.

Common situations: Pasting CLDR month objects that wrap the name in metadata; mis-indenting list items so they become mappings; converting from a structured calendar format.

Related errors


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