{"record":{"id":"62620e8264f22c6d","repo":"Humanizr/Humanizer","slug":"case-aware-citation-phrases-for-catalog-localeco","errorCode":null,"errorMessage":"Case-aware citation phrases for '{catalog.LocaleCode}' require the duration phrase surface.","messagePattern":"Case-aware citation phrases for '(.+?)' require the duration phrase surface\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs","lineNumber":903,"sourceCode":"                    $\"Case overlay '{path}.multiple.forms' must explicitly define reachable '{requiredForm}' form.\");\n            }\n        }\n\n        static void ValidateCitationBaseDurationForms(\n            DurationCaseCatalog catalog,\n            SimpleYamlValue? phrasesValue,\n            ImmutableArray<string> requiredMultipleForms)\n        {\n            if (!catalog.Realizations.TryGetValue(catalog.CitationCase, out var citation) ||\n                citation.Kind != DurationCaseRealizationKind.Authored ||\n                citation.Units.Count != 0)\n            {\n                return;\n            }\n\n            var path = $\"{catalog.LocaleCode}.phrases.duration\";\n            var phrases = phrasesValue is null\n                ? throw new InvalidOperationException(\n                    $\"Case-aware citation phrases for '{catalog.LocaleCode}' require the duration phrase surface.\")\n                : ExpectMapping(phrasesValue, $\"{catalog.LocaleCode}.phrases\");\n            if (!phrases.TryGetValue(\"duration\", out var durationValue))\n            {\n                throw new InvalidOperationException(\n                    $\"Case-aware citation phrases for '{catalog.LocaleCode}' require '{path}'.\");\n            }\n\n            var duration = ExpectMapping(durationValue, path);\n            foreach (var unitName in TimeUnits)\n            {\n                if (!duration.TryGetValue(unitName, out var phraseValue))\n                {\n                    throw new InvalidOperationException(\n                        $\"Case-aware citation phrases for '{catalog.LocaleCode}' require '{path}.{unitName}'.\");\n                }\n\n                ValidateReachableMultipleForms(","sourceCodeStart":885,"sourceCodeEnd":921,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs#L885-L921","documentation":"Thrown by ValidateCitationBaseDurationForms when a locale has a case-aware authored citation case (the citation realization kind is Authored with no authored units) but the top-level 'phrases' section passed to the parser is null. The citation case then has no duration phrase surface to fall back on, so the generator cannot resolve base-duration forms.","triggerScenarios":"The locale YAML defines durationCases with an authored citation case (units count is 0) but does not provide a 'phrases' block at all, so phrasesValue is null when DurationCaseNormalization.Parse is called.","commonSituations":"A locale declares a durationCases structure with a citation case that relies on the base phrases.duration surface, but the locale file (or the caller) omits the phrases section entirely. This typically happens when a contributor splits durationCases into a separate file or partial and forgets to pass the phrases reference.","solutions":["Ensure the locale YAML includes a 'phrases' section with at least a 'duration' sub-mapping.","Pass the phrases value to DurationCaseNormalization.Parse via the phrases parameter so the citation case can validate its base-duration forms.","If the locale genuinely has no duration phrases, mark the citation case as notApplicable or unsupported instead of authored."],"exampleFix":"# before — locale file has durationCases but no phrases\nphrases: ~\ndurationCases:\n  ...\n# after\nphrases:\n  duration:\n    second:\n      ...\ndurationCases:\n  ...","handlingStrategy":"validation","validationCode":"# Verify the locale file has a non-null 'phrases' section when durationCases is present\n# python: if 'durationCases' in yaml and not yaml.get('phrases'): print('MISSING phrases')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure every locale YAML that declares durationCases also includes a phrases.duration section.","When splitting locale data across files, pass the phrases reference to the parser.","If the locale has no duration phrases at all, mark the citation case as notApplicable instead of authored."],"tags":["humanizer","locale","yaml","source-generator","duration-cases","citation","build-time"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}