{"record":{"id":"ef76275df29fa3ff","repo":"Humanizr/Humanizer","slug":"case-overlay-path-must-explicitly-define-singu","errorCode":null,"errorMessage":"Case overlay '{path}' must explicitly define singular and numeric multiple forms.","messagePattern":"Case overlay '(.+?)' must explicitly define singular and numeric multiple forms\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs","lineNumber":1182,"sourceCode":"                return new DurationCaseUnit(DurationCaseUnitKind.SameAsNominative, null);\n            }\n\n            if (mapping.GetScalar(\"unsupported\") is { } unsupported)\n            {\n                RejectUnknownKeys(mapping, path, [\"unsupported\"]);\n                if (!bool.TryParse(unsupported, out var enabled) || !enabled)\n                {\n                    throw new InvalidOperationException($\"'{path}.unsupported' must be true.\");\n                }\n\n                return new DurationCaseUnit(DurationCaseUnitKind.Unsupported, null);\n            }\n\n            var phrase = LocalePhraseNormalization.ParseTimeSpanPhrase(value, path);\n            if (phrase.Single is null ||\n                phrase.Multiple?.Forms is null)\n            {\n                throw new InvalidOperationException(\n                    $\"Case overlay '{path}' must explicitly define singular and numeric multiple forms.\");\n            }\n\n            return new DurationCaseUnit(DurationCaseUnitKind.Phrase, phrase);\n        }\n\n        static bool ContainsInheritanceMarker(SimpleYamlValue value) =>\n            value switch\n            {\n                SimpleYamlScalar scalar => scalar.Value.Contains(\"↑↑↑\", StringComparison.Ordinal),\n                SimpleYamlMapping mapping => mapping.Values.Values.Any(ContainsInheritanceMarker),\n                SimpleYamlSequence sequence => sequence.Items.Any(ContainsInheritanceMarker),\n                _ => false\n            };\n\n        static SimpleYamlMapping ExpectMapping(SimpleYamlValue value, string path) =>\n            value as SimpleYamlMapping\n            ?? throw new InvalidOperationException($\"'{path}' must be a mapping.\");","sourceCodeStart":1164,"sourceCodeEnd":1200,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/DurationCaseModels.cs#L1164-L1200","documentation":"After sameAsNominative/unsupported checks, ParseUnit (DurationCaseModels.cs:1178-1184) parses the unit as a TimeSpan phrase via LocalePhraseNormalization.ParseTimeSpanPhrase and requires both phrase.Single and phrase.Multiple?.Forms to be non-null. A phrase unit missing its singular form or its numeric multiple forms is rejected so generated code always has both.","triggerScenarios":"A unit's phrase: block has single: but no multiple: (or multiple: without forms:), or vice-versa.","commonSituations":"Incomplete phrase authoring; copying a phrase block from a locale whose multiple-form shape differs; forgetting the forms: level under multiple:.","solutions":["Add the missing half: ensure phrase.single (with numeric/words) AND phrase.multiple.forms (default/singular/etc.) both exist.","If only the singular exists and no plural is needed, still provide a multiple.forms entry (often mirroring the singular).","If the unit should not have a phrase, switch it to sameAsNominative: true or unsupported: true."],"exampleFix":"# before - multiple missing forms\nsecond:\n  phrase:\n    single: { numeric: '1 sekunda', words: 'jedna sekunda' }\n    multiple: {}\n# after\nsecond:\n  phrase:\n    single: { numeric: '1 sekunda', words: 'jedna sekunda' }\n    multiple:\n      forms: { default: 'sekund', singular: 'sekundy', plural: 'sekund' }","handlingStrategy":"validation","validationCode":"# A phrase unit must define single and multiple.forms\nforeach ($u in $caseUnits.GetEnumerator()) {\n    $v = $u.Value\n    if ($v -is [hashtable] -and $v.ContainsKey('phrase')) {\n        $p = $v.phrase\n        if (-not $p.single -or -not $p.multiple -or -not $p.multiple.forms) {\n            throw \"unit '$($u.Key)' phrase must define single and multiple.forms\"\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always author phrase blocks with both single: (numeric/words) and multiple:forms:.","Copy a complete phrase block from a sibling unit as a template.","If a phrase is not appropriate, use sameAsNominative or unsupported instead."],"tags":["source-generator","build-time","localization","yaml","duration-cases","phrase","locale-data"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}