{"record":{"id":"9fc34f74e3befe7e","repo":"Humanizr/Humanizer","slug":"ordinal-date-profile-profile-profilename-has-c-9fc34f","errorCode":null,"errorMessage":"Ordinal date profile '{profile.ProfileName}' has calendar month overrides but pattern contains multiple unescaped MMMM specifiers. Only one is supported.","messagePattern":"Ordinal date profile '(.+?)' has calendar month overrides but pattern contains multiple unescaped MMMM specifiers\\. Only one is supported\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/OrdinalDateProfileCatalogInput.cs","lineNumber":209,"sourceCode":"                throw new InvalidOperationException(\n                    $\"Ordinal date profile '{profile.ProfileName}' uses MMM (abbreviated month) \" +\n                    \"which is not supported when calendar month overrides are active. \" +\n                    \"Only MMMM (full month name) substitution is supported.\");\n            }\n\n            if (hasAnyMonthOverride)\n            {\n                var mmmmCount = CountUnescapedFullMonth(pattern);\n                if (mmmmCount == 0)\n                {\n                    throw new InvalidOperationException(\n                        $\"Ordinal date profile '{profile.ProfileName}' has calendar month overrides \" +\n                        \"but pattern does not contain an unescaped MMMM specifier.\");\n                }\n\n                if (mmmmCount > 1)\n                {\n                    throw new InvalidOperationException(\n                        $\"Ordinal date profile '{profile.ProfileName}' has calendar month overrides \" +\n                        \"but pattern contains multiple unescaped MMMM specifiers. Only one is supported.\");\n                }\n            }\n\n            var calendarMode = GetOptionalString(profile.Root, \"calendarMode\");\n            var hasCalendarMode = calendarMode is not null && !string.Equals(calendarMode, \"Gregorian\", StringComparison.OrdinalIgnoreCase);\n\n            var expr = \"new \" + converterTypeName + \"(new OrdinalDatePattern(\" +\n                       QuoteLiteral(pattern) +\n                       \", OrdinalDateDayMode.\" +\n                       GetRequiredString(profile.Root, \"dayMode\");\n\n            if (hasCalendarMode)\n            {\n                var normalized = char.ToUpperInvariant(calendarMode![0]) + calendarMode.Substring(1).ToLowerInvariant();\n                expr += \", OrdinalDateCalendarMode.\" + normalized;\n            }","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/OrdinalDateProfileCatalogInput.cs#L191-L227","documentation":"Thrown during source generation by CreatePatternExpression when an ordinal-date profile has calendar month overrides and the pattern contains more than one unescaped MMMM specifier. The generator supports exactly one MMMM substitution point; multiple unescaped MMMM tokens make the substitution target ambiguous, so it rejects the pattern.","triggerScenarios":"A locale YAML defines calendar.months or calendar.hijriMonths and the ordinal-date pattern contains MMMM twice (both unescaped), e.g. 'MMMM dd, MMMM yyyy'. CountUnescapedFullMonth returns a count greater than 1.","commonSituations":"A maintainer designs a verbose pattern that repeats the month name for emphasis or formatting, while also providing month overrides. Or the pattern was copied from another locale that happened to repeat the month.","solutions":["Reduce the pattern to contain exactly one unescaped MMMM specifier.","If a second month reference is needed, escape it in single quotes so it is treated as a literal (e.g. 'MMMM dd yyyy (\\'MMMM\\')' — though note this displays the literal text, not the month).","Remove the calendar month overrides if multiple month substitutions are genuinely needed (relying on ICU-supplied names instead)."],"exampleFix":"# locale YAML — before (two unescaped MMMM)\nordinalDate:\n  engine: pattern\n  pattern: \"MMMM dd, MMMM yyyy\"\ncalendar:\n  months:\n    - January\n\n# after — single unescaped MMMM\nordinalDate:\n  engine: pattern\n  pattern: \"dd MMMM yyyy\"\ncalendar:\n  months:\n    - January","handlingStrategy":"validation","validationCode":"// Before building, if a locale YAML has calendar month overrides for\n// ordinal dates, verify the pattern contains exactly one unescaped MMMM.\n// CountUnescapedFullMonth must return 1.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure the ordinal-date pattern has exactly one unescaped MMMM when calendar month overrides are present.","Escape any additional MMMM tokens in single quotes if they are meant as literals.","Remove month overrides if multiple month substitutions are needed."],"tags":["source-generator","locale-yaml","ordinal-date","calendar","date-format","build-time"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}