Humanizr/Humanizer · error · InvalidOperationException
Template '{path}' can only use placeholders: {allowedPlaceho
Error message
Template '{path}' can only use placeholders: {allowedPlaceholders}. What it means
Thrown by CreateNamedTemplatePhrase when a template uses a placeholder name that is syntactically valid but not in the allowed set for that surface. Each surface restricts templates to specific names (e.g. dataUnit/timeUnit templates allow count and unit; counted-phrase templates allow count, unit, prep). Surfaced as compiler diagnostic HSG003 (severity Error).
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs:457
{
var placeholders = ImmutableArray.CreateBuilder<string>();
foreach (var placeholderName in GetPlaceholderNames(template))
{
if (int.TryParse(placeholderName, out _))
{
throw new InvalidOperationException($"Template '{path}' cannot use numeric placeholder '{{{placeholderName}}}'.");
}
if (placeholderName.Length == 0 || !char.IsLetter(placeholderName[0]) || placeholderName.Any(static c => !char.IsLetterOrDigit(c) && c != '_'))
{
throw new InvalidOperationException($"Template '{path}' uses unsupported placeholder '{{{placeholderName}}}'.");
}
if (!allowedPlaceholders.Contains(placeholderName, StringComparer.Ordinal))
{
throw new InvalidOperationException(
$"Template '{path}' can only use placeholders: {string.Join(", ", allowedPlaceholders.Select(static value => $"{{{value}}}"))}.");
}
if (!placeholders.Contains(placeholderName))
{
placeholders.Add(placeholderName);
}
}
return new NamedTemplatePhrase(templateName, template, placeholders.ToImmutable());
}
static string? GetOptionalLiteral(SimpleYamlMapping mapping, string key, string path, params string[] allowedPlaceholders)
{
if (!mapping.TryGetValue(key, out var value))
{
return null;
}
View on GitHub (pinned to ffc2b77c0f)
Solutions
- Read the diagnostic: it lists the allowed placeholders for that exact path.
- Replace the disallowed placeholder with one from the allowed set, or remove it.
- Rebuild to confirm the diagnostic clears.
Example fix
# before (data unit template)
dataUnits:
byte:
template:
value: '{value}'
# after
dataUnits:
byte:
template:
value: '{count} {unit}' Defensive patterns
Strategy: validation
Validate before calling
# Per-surface allowed placeholders:
# dataUnits/timeUnits templates: {count}, {unit}
# counted-phrase templates: {count}, {unit}, {prep}
# duration 'age' template: {value}
# Review each template value against its surface's allow-list before building. Prevention
- Learn the placeholder vocabulary per surface (the HSG003 message lists it).
- Do not assume a placeholder valid on one surface works elsewhere.
- Build after editing templates.
When it happens
Trigger: Writing a data-unit template with '{value}' or '{name}', or a duration template (allowed placeholders: none) with any placeholder.
Common situations: Author reuses a placeholder valid on one surface on a different surface where it is not supported; assuming all surfaces share the same placeholder vocabulary.
Related errors
- Template '{path}' cannot use numeric placeholder '{{placehol
- Template '{path}' uses unsupported placeholder '{{placeholde
- Phrase '{path}' can only use placeholders in explicit 'templ
- Template '{path}' must define a scalar 'value'.
- Phrase '{path}' must define a scalar string or an explicit '
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/eff20f9cf6e58943.
Report an issue: GitHub.