Humanizr/Humanizer · error · InvalidOperationException

Ordinal date profile '{profile.ProfileName}' uses MMM (abbre

Error message

Ordinal date profile '{profile.ProfileName}' uses MMM (abbreviated month) which is not supported when calendar month overrides are active. Only MMMM (full month name) substitution is supported.

What it means

Thrown during source generation by CreatePatternExpression when an ordinal-date profile has calendar month overrides (Gregorian or Hijri months defined) AND its pattern string contains an unescaped MMM (abbreviated month) specifier. The generator only knows how to substitute full month names (MMMM) from the calendar override; abbreviated months (MMM) are not supported in that mode.

Source

Thrown at src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/OrdinalDateProfileCatalogInput.cs:191

                {
                    "PatternDateToOrdinalWordsConverter" => "new DefaultDateToOrdinalWordConverter()",
                    "PatternDateOnlyToOrdinalWordsConverter" => "new DefaultDateOnlyToOrdinalWordConverter()",
                    _ => throw new InvalidOperationException($"Unsupported default ordinal-date converter '{converterTypeName}'.")
                },
                "pattern" => CreatePatternExpression(profile, converterTypeName),
                _ => throw new InvalidOperationException($"Unsupported ordinal date engine '{profile.Engine}'.")
            };

        static string CreatePatternExpression(OrdinalDateProfileDefinition profile, string converterTypeName)
        {
            var pattern = GetRequiredString(profile.Root, "pattern");
            var hasGregorianMonths = profile.Months.Length > 0;
            var hasHijriMonths = profile.HijriMonths.Length > 0;
            var hasAnyMonthOverride = hasGregorianMonths || hasHijriMonths;

            if (hasAnyMonthOverride && ContainsAbbreviatedMonth(pattern))
            {
                throw new InvalidOperationException(
                    $"Ordinal date profile '{profile.ProfileName}' uses MMM (abbreviated month) " +
                    "which is not supported when calendar month overrides are active. " +
                    "Only MMMM (full month name) substitution is supported.");
            }

            if (hasAnyMonthOverride)
            {
                var mmmmCount = CountUnescapedFullMonth(pattern);
                if (mmmmCount == 0)
                {
                    throw new InvalidOperationException(
                        $"Ordinal date profile '{profile.ProfileName}' has calendar month overrides " +
                        "but pattern does not contain an unescaped MMMM specifier.");
                }

                if (mmmmCount > 1)
                {
                    throw new InvalidOperationException(

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Change the pattern to use MMMM (full month name) instead of MMM (abbreviated month) so the generator can substitute from the calendar override.
  2. If you truly need abbreviated months, remove the calendar.months and calendar.hijriMonths overrides so the pattern relies on ICU-supplied month names.
  3. Ensure the MMM is not inside a quoted literal section (e.g. 'dd \'MMM\' yyyy') — escape it properly if it is meant as a literal.

Example fix

# locale YAML — before (conflict: month override + abbreviated month)
ordinalDate:
  engine: pattern
  pattern: "dd MMM yyyy"
calendar:
  months:
    - January
    - February

# after — use full month name
ordinalDate:
  engine: pattern
  pattern: "dd MMMM yyyy"
calendar:
  months:
    - January
    - February
Defensive patterns

Strategy: validation

Validate before calling

// Before building, if a locale YAML has calendar month overrides for
// ordinal dates, verify the pattern uses MMMM (not MMM) for months.
// MMM is unsupported when overrides are active.

Prevention

When it happens

Trigger: A locale YAML defines a calendar.months or calendar.hijriMonths sequence for the ordinal-date profile, and the pattern property contains 'MMM' (the .NET abbreviated-month format token). The generator detects this conflict and rejects it because it cannot inject abbreviated month names from the override list.

Common situations: A maintainer copies a date format pattern from another locale or feature that uses abbreviated months, while simultaneously adding calendar month overrides for full month names.

Related errors


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