{"record":{"id":"4354e57c08024916","repo":"Humanizr/Humanizer","slug":"template-path-uses-unsupported-placeholder","errorCode":null,"errorMessage":"Template '{path}' uses unsupported placeholder '{{placeholderName}}'.","messagePattern":"Template '(.+?)' uses unsupported placeholder '(.+?)\\}'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs","lineNumber":451,"sourceCode":"            }\n\n            return CreateNamedTemplatePhrase(name, templateScalar.Value, path, allowedPlaceholders);\n        }\n\n        static NamedTemplatePhrase CreateNamedTemplatePhrase(string? templateName, string template, string path, params string[] allowedPlaceholders)\n        {\n            var placeholders = ImmutableArray.CreateBuilder<string>();\n\n            foreach (var placeholderName in GetPlaceholderNames(template))\n            {\n                if (int.TryParse(placeholderName, out _))\n                {\n                    throw new InvalidOperationException($\"Template '{path}' cannot use numeric placeholder '{{{placeholderName}}}'.\");\n                }\n\n                if (placeholderName.Length == 0 || !char.IsLetter(placeholderName[0]) || placeholderName.Any(static c => !char.IsLetterOrDigit(c) && c != '_'))\n                {\n                    throw new InvalidOperationException($\"Template '{path}' uses unsupported placeholder '{{{placeholderName}}}'.\");\n                }\n\n                if (!allowedPlaceholders.Contains(placeholderName, StringComparer.Ordinal))\n                {\n                    throw new InvalidOperationException(\n                        $\"Template '{path}' can only use placeholders: {string.Join(\", \", allowedPlaceholders.Select(static value => $\"{{{value}}}\"))}.\");\n                }\n\n                if (!placeholders.Contains(placeholderName))\n                {\n                    placeholders.Add(placeholderName);\n                }\n            }\n\n            return new NamedTemplatePhrase(templateName, template, placeholders.ToImmutable());\n        }\n\n        static string? GetOptionalLiteral(SimpleYamlMapping mapping, string key, string path, params string[] allowedPlaceholders)","sourceCodeStart":433,"sourceCodeEnd":469,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs#L433-L469","documentation":"Thrown by CreateNamedTemplatePhrase when a template placeholder name is empty, does not start with a letter, or contains characters other than letters, digits, or underscore. Placeholder names must be valid identifiers. Surfaced as compiler diagnostic HSG003 (severity Error).","triggerScenarios":"Writing a template with a malformed placeholder such as '{}', '{ count}', '{1st}', '{count-unit}', or '{count!}'.","commonSituations":"Stray whitespace inside braces; using hyphens in placeholder names; leftover brace pairs from editing; markdown-style placeholders.","solutions":["Make each placeholder an identifier: start with a letter, use only letters/digits/underscores, no spaces.","Use the underscore convention for multi-word placeholders if needed (e.g. {unit_count}), but prefer one of the allowed names.","Rebuild to confirm the diagnostic clears."],"exampleFix":"# before\ntemplate:\n  value: '{ count } {unit}'\n# after\ntemplate:\n  value: '{count} {unit}'","handlingStrategy":"validation","validationCode":"# Find malformed placeholders (empty, bad start char, illegal chars) in template values.\ngrep -nE 'value:.*\\{(\\s*|[^A-Za-z_][^}]*|[^}]*[^A-Za-z0-9_][^}]*)\\}' src/Humanizer/Locales/<code>.yml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep placeholders tight: {name}, no inner spaces or punctuation.","Start placeholder names with a letter.","Build to catch malformed braces."],"tags":["humanizer","source-generator","locale","yaml","localization","phrases","template","placeholder"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}