{"record":{"id":"da0388e7944e384e","repo":"Humanizr/Humanizer","slug":"case-overlay-path-multiple-forms-must-explicit","errorCode":null,"errorMessage":"Case overlay '{path}.multiple.forms' must explicitly define reachable '{requiredForm}' form.","messagePattern":"Case overlay '(.+?)\\.multiple\\.forms' must explicitly define reachable '(.+?)' form\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs","lineNumber":884,"sourceCode":"            if (multiple.TryGetValue(\"forms\", out var formsValue))\n            {\n                hasScalarDefault = formsValue is SimpleYamlScalar;\n                forms = formsValue as SimpleYamlMapping;\n            }\n            else\n            {\n                forms = multiple;\n            }\n\n            foreach (var requiredForm in requiredMultipleForms)\n            {\n                if ((requiredForm == \"default\" && hasScalarDefault) ||\n                    forms?.TryGetValue(requiredForm, out _) == true)\n                {\n                    continue;\n                }\n\n                throw new InvalidOperationException(\n                    $\"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","sourceCodeStart":866,"sourceCodeEnd":902,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs#L866-L902","documentation":"Thrown by ValidateReachableMultipleForms after confirming a 'multiple' key exists, when the locale's plural rule requires a specific named form (e.g. 'dual', 'paucal', 'plural') that is not present in the multiple.forms mapping. The validator iterates the requiredMultipleForms array and throws on the first missing form.","triggerScenarios":"The phrase defines a 'multiple.forms' mapping but omits a form that GetRequiredMultipleForms mandates for the locale's plural rule. For example, an 'arabic-like' locale missing 'dual', or a 'slovenian' locale missing 'paucal'.","commonSituations":"A contributor copies a phrase from a singular-plural locale into an Arabic-like or Slavic locale without adding the extra plural categories. Also occurs when the 'forms' sub-key is a scalar (string) instead of a mapping, leaving all named forms unreachable.","solutions":["Look up the required forms for the locale's plural rule in GetRequiredMultipleForms (e.g. arabic-cardinal needs default, zero, dual, plural, many).","Add the missing named form(s) to the 'multiple.forms' mapping at the reported path.","Ensure 'forms' is a mapping (keyed by form name) and not a scalar string unless only 'default' is required.","Rebuild to confirm all required forms are reachable."],"exampleFix":"# before (slovenian locale; missing 'dual' and 'paucal')\nsecond:\n  phrase:\n    multiple:\n      forms:\n        default: sekund\n# after\nsecond:\n  phrase:\n    multiple:\n      forms:\n        default: sekund\n        dual: sekundi\n        paucal: sekunde","handlingStrategy":"validation","validationCode":"# Map plural rule to required forms and verify each phrase has them\n$ruleMap = @{\n    'singular-plural' = @('default','plural')\n    'arabic-like' = @('default','dual','plural')\n    'arabic-cardinal' = @('default','zero','dual','plural','many')\n    'polish' = @('default','paucal')\n    'slovenian' = @('default','dual','paucal')\n}\n# For each phrase, check that multiple.forms contains all required form names","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Look up the required forms for the locale's plural rule in the GetRequiredMultipleForms switch table.","Ensure 'multiple.forms' is a mapping keyed by form name, not a scalar.","Add a unit test that exercises the locale's duration output for cardinal numbers covering all plural categories."],"tags":["humanizer","locale","yaml","source-generator","duration-cases","phrase","plural-form","build-time"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}