Humanizr/Humanizer · error · InvalidOperationException
Phrase '{path}' uses unsupported placeholder '{{placeholder}
Error message
Phrase '{path}' uses unsupported placeholder '{{placeholder}}'. What it means
Thrown by ValidateLiteralText when a literal phrase string contains a placeholder whose name is empty, does not start with a letter, or contains non-identifier characters. Literal placeholders must be valid identifiers. Surfaced as compiler diagnostic HSG003 (severity Error).
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs:522
{
throw new InvalidOperationException($"Phrase '{path}' must define a scalar string or an explicit 'template'.");
}
return ParseNamedTemplate(templateValue, $"{path}.template", ["value"]).Template;
}
static string ValidateLiteralText(string path, string text, params string[] allowedPlaceholders)
{
foreach (var placeholder in GetPlaceholderNames(text))
{
if (int.TryParse(placeholder, out _))
{
throw new InvalidOperationException($"Phrase '{path}' cannot use numeric placeholder '{{{placeholder}}}'.");
}
if (placeholder.Length == 0 || !char.IsLetter(placeholder[0]) || placeholder.Any(static c => !char.IsLetterOrDigit(c) && c != '_'))
{
throw new InvalidOperationException($"Phrase '{path}' uses unsupported placeholder '{{{placeholder}}}'.");
}
if (!allowedPlaceholders.Contains(placeholder, StringComparer.Ordinal))
{
throw new InvalidOperationException(
allowedPlaceholders.Length == 0
? $"Phrase '{path}' can only use placeholders in explicit 'template' entries."
: $"Phrase '{path}' can only use placeholders: {string.Join(", ", allowedPlaceholders.Select(static value => $"{{{value}}}"))}.");
}
}
return text;
}
static IEnumerable<string> GetPlaceholderNames(string text) =>
PlaceholderRegex.Matches(text)
.Cast<Match>()
.Select(static match => match.Groups["name"].Value);View on GitHub (pinned to ffc2b77c0f)
Solutions
- Remove the malformed placeholder from the literal, or use only an allowed identifier placeholder where permitted.
- Move dynamic formatting into an explicit 'template' entry if a placeholder is genuinely needed.
- Rebuild to confirm the diagnostic clears.
Example fix
# before
forms:
default: '{ count } hours'
# after
forms:
default: hours Defensive patterns
Strategy: validation
Validate before calling
# Find malformed placeholders inside literal string fields.
grep -nE '(symbol|default|zero|singular|dual|paucal|plural|many|beforeCount|afterCount):.*\{(\s*|[^A-Za-z_][^}]*|[^}]*[^A-Za-z0-9_][^}]*)\}' src/Humanizer/Locales/<code>.yml Prevention
- Avoid placeholders in literals altogether.
- If a brace is needed literally, quote the value and avoid the { } pattern.
- Build after editing.
When it happens
Trigger: Writing a literal with '{}', '{ count}', '{count-unit}', or '{count!}'.
Common situations: Stray whitespace or punctuation inside braces; hyphenated placeholder names; leftover brace pairs.
Related errors
- Phrase '{path}' cannot use numeric placeholder '{{placeholde
- Phrase '{path}' can only use placeholders in explicit 'templ
- Phrase '{path}' can only use placeholders: {allowedPlacehold
- Template '{path}' cannot use numeric placeholder '{{placehol
- Template '{path}' uses unsupported placeholder '{{placeholde
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/ede2b9e0c7cd9e6d.
Report an issue: GitHub.