{"record":{"id":"ffd99d6edee383a7","repo":"Humanizr/Humanizer","slug":"phrase-forms-path-must-define-at-least-one-for","errorCode":null,"errorMessage":"Phrase forms '{path}' must define at least one form.","messagePattern":"Phrase forms '(.+?)' must define at least one form\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs","lineNumber":384,"sourceCode":"        }\n\n        static PhraseForms ParsePhraseForms(\n            SimpleYamlValue value,\n            string path,\n            bool preserveDuplicateForms,\n            params string[] allowedPlaceholders)\n        {\n            if (value is SimpleYamlScalar scalar)\n            {\n                var scalarForms = PhraseForms.FromScalar(ValidateLiteralText(path, scalar.Value, allowedPlaceholders));\n                return preserveDuplicateForms ? scalarForms : scalarForms.CollapseDuplicates();\n            }\n\n            var mapping = ExpectMapping(value, path);\n            RejectUnknownKeys(mapping, path, [\"default\", \"zero\", \"singular\", \"dual\", \"paucal\", \"plural\", \"many\"]);\n            if (!TryParseDirectPhraseForms(mapping, path, out var forms, allowedPlaceholders))\n            {\n                throw new InvalidOperationException($\"Phrase forms '{path}' must define at least one form.\");\n            }\n\n            return preserveDuplicateForms ? forms : forms.CollapseDuplicates();\n        }\n\n        static bool TryParseDirectPhraseForms(SimpleYamlMapping mapping, string path, out PhraseForms forms, params string[] allowedPlaceholders)\n        {\n            var defaultValue = GetOptionalLiteral(mapping, \"default\", $\"{path}.default\", allowedPlaceholders);\n            var zero = GetOptionalLiteral(mapping, \"zero\", $\"{path}.zero\", allowedPlaceholders);\n            var singular = GetOptionalLiteral(mapping, \"singular\", $\"{path}.singular\", allowedPlaceholders);\n            var dual = GetOptionalLiteral(mapping, \"dual\", $\"{path}.dual\", allowedPlaceholders);\n            var paucal = GetOptionalLiteral(mapping, \"paucal\", $\"{path}.paucal\", allowedPlaceholders);\n            var plural = GetOptionalLiteral(mapping, \"plural\", $\"{path}.plural\", allowedPlaceholders);\n            var many = GetOptionalLiteral(mapping, \"many\", $\"{path}.many\", allowedPlaceholders);\n\n            defaultValue ??= zero ?? singular ?? dual ?? paucal ?? plural ?? many;\n            if (defaultValue is null)\n            {","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs#L366-L402","documentation":"Thrown by ParsePhraseForms when a 'forms' mapping contains none of the recognized form keys (default, zero, singular, dual, paucal, plural, many). At least one form is required so the phrase has a fallback rendering. Surfaced as compiler diagnostic HSG003 (severity Error).","triggerScenarios":"Authoring a forms: {} empty mapping, or a forms mapping that uses only unrecognized keys (typos like 'one'/'many2' instead of singular/plural).","commonSituations":"Translating only some forms and accidentally deleting the default/singular key; mistyping a form key; leaving forms: as a placeholder.","solutions":["Add at least one recognized form key (default, zero, singular, dual, paucal, plural, many) to the forms mapping.","Ensure 'default' is set so all uncovered counts fall back to it.","Rebuild to confirm the HSG003 diagnostic clears."],"exampleFix":"# before\nforms: {}\n# after\nforms:\n  default: hours\n  singular: hour\n  plural: hours","handlingStrategy":"validation","validationCode":"# A forms mapping must contain at least one of the known form keys.\nknown=[default zero singular dual paucal plural many]\nyq -o=json '.phrases | .. | select(has(\"forms\")) | .forms | select(tag == \"!!map\") | select([keys[] | select(. as $k | $known | index($k))] | length == 0)' src/Humanizer/Locales/<code>.yml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set 'default' as the fallback form.","Use the exact key names (singular, plural, etc.); avoid synonyms like 'one'.","Build after authoring forms to catch empty/typo mappings."],"tags":["humanizer","source-generator","locale","yaml","localization","phrases","forms"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}