Humanizr/Humanizer · critical · InvalidOperationException

Locale '{localeCode}.surfaces.calendar.hijriMonths' must be

Error message

Locale '{localeCode}.surfaces.calendar.hijriMonths' must be a sequence of exactly 12 strings.

What it means

Thrown by AddCalendarFeatures when surfaces.calendar.hijriMonths is present but is not a YAML sequence of exactly 12 entries. The Hijri calendar has twelve months (Muharram..Dhu al-Hijjah), so the build enforces the exact length.

Source

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

                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.");
                }

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

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

                foreach (var item in hijriSeq.Items)
                {
                    if (item is not SimpleYamlScalar scalar)
                    {
                        throw new InvalidOperationException(
                            $"Locale '{localeCode}.surfaces.calendar.hijriMonths' items must be scalar strings.");
                    }

                    if (scalar.Value.IndexOfAny(['\u200E', '\u200F', '\u061C']) >= 0)
                    {
                        throw new InvalidOperationException(
                            $"Locale '{localeCode}.surfaces.calendar.hijriMonths' must not contain directionality controls (U+200E, U+200F, U+061C).");
                    }
                }
            }

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Provide exactly 12 Hijri month strings in surfaces.calendar.hijriMonths.
  2. Cross-check against a reference Arabic/Islamic locale to confirm month order and count.
  3. Rebuild to confirm the length guard passes.

Example fix

# before
calendar:
  hijriMonths: [Muharram, Safar]
# after
calendar:
  hijriMonths: [Muharram, Safar, Rabi al-Awwal, Rabi al-Thani, Jumada al-Awwal, Jumada al-Thani, Rajab, Shaban, Ramadan, Shawwal, Dhu al-Qidah, Dhu al-Hijjah]
Defensive patterns

Strategy: validation

Validate before calling

# Ensure surfaces.calendar.hijriMonths is a 12-element sequence.
# Parse the YAML and assert: $hijri -is [array] -and $hijri.Count -eq 12.

Prevention

When it happens

Trigger: A locale YAML defines hijriMonths with fewer/more than 12 entries, as a mapping, or as a scalar. The guard at CanonicalLocaleAuthoring.cs:496-500 requires a SimpleYamlSequence of length 12.

Common situations: Translating only some Hijri month names; pasting from a source that abbreviated or merged months; miscounting when porting CLDR islamic-month data.

Related errors


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