{"record":{"id":"33138a23097a3a77","repo":"Humanizr/Humanizer","slug":"template-path-cannot-use-numeric-placeholder","errorCode":null,"errorMessage":"Template '{path}' cannot use numeric placeholder '{{placeholderName}}'.","messagePattern":"Template '(.+?)' cannot use numeric placeholder '(.+?)\\}'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs","lineNumber":446,"sourceCode":"            RejectUnknownKeys(mapping, path, [\"name\", \"value\"]);\n            var name = GetOptionalLiteral(mapping, \"name\", $\"{path}.name\");\n            if (!mapping.TryGetValue(\"value\", out var templateValue) || templateValue is not SimpleYamlScalar templateScalar)\n            {\n                throw new InvalidOperationException($\"Template '{path}' must define a scalar 'value'.\");\n            }\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            }","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs#L428-L464","documentation":"Thrown by CreateNamedTemplatePhrase when a template 'value' string contains a numeric placeholder like {0} or {1}. Humanizer templates use named placeholders (e.g. {count}, {unit}), never positional indices. Surfaced as compiler diagnostic HSG003 (severity Error).","triggerScenarios":"Authoring a template value with string.Format-style indices such as '{0} {1}' or '{0}'.","commonSituations":"Copy-paste from C# string.Format code; habit from other localization systems that use numeric placeholders; misunderstanding the template syntax.","solutions":["Replace numeric placeholders with the allowed named ones for that surface (e.g. {count}, {unit}, {value}, {prep}).","Check the error's sibling message (149) which lists the placeholders permitted at that path.","Rebuild to confirm the diagnostic clears."],"exampleFix":"# before\ntemplate:\n  value: '{0} {1} ago'\n# after\ntemplate:\n  value: '{count} {unit} ago'","handlingStrategy":"validation","validationCode":"# Reject numeric placeholders inside template values.\ngrep -nE 'template:.*\\{[0-9]+\\}' src/Humanizer/Locales/<code>.yml\n# Also catch block-style: grep -nE 'value:.*\\{[0-9]+\\}' for value: lines.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use named placeholders only ({count}, {unit}, {value}, {prep}).","Never copy string.Format patterns verbatim into locale YAML.","Build after migrating format strings."],"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-14T05:17:29.042Z"}