Humanizr/Humanizer · error · InvalidOperationException
Phrase '{path}' must define a scalar string or an explicit '
Error message
Phrase '{path}' must define a scalar string or an explicit 'template'. What it means
Thrown by GetOptionalLiteralOrExplicitTemplate (used for the duration 'age' field) when the value is a mapping that does not contain a 'template' key. The age field may be a scalar string or a mapping whose only key is 'template'. Surfaced as compiler diagnostic HSG003 (severity Error).
Source
Thrown at src/Humanizer.SourceGenerators/Common/LocalePhraseNormalization.cs:505
}
static string? GetOptionalLiteralOrExplicitTemplate(SimpleYamlMapping mapping, string key, string path)
{
if (!mapping.TryGetValue(key, out var value))
{
return null;
}
if (value is SimpleYamlScalar scalar)
{
return ValidateLiteralText(path, scalar.Value);
}
var templateMapping = ExpectMapping(value, path);
RejectUnknownKeys(templateMapping, path, ["template"]);
if (!templateMapping.TryGetValue("template", out var templateValue))
{
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}}}'.");
}View on GitHub (pinned to ffc2b77c0f)
Solutions
- Make age a scalar string, or a mapping containing exactly a 'template' entry.
- Remove the age key if the locale does not customize it.
- Rebuild to confirm the diagnostic clears.
Example fix
# before
duration:
age:
format: years
# after
duration:
age:
template:
value: '{value} old' Defensive patterns
Strategy: validation
Validate before calling
# The 'age' field must be a scalar or a mapping whose only key is 'template'.
yq -o=json '.phrases.duration.age | select(tag == "!!map" and (has("template") | not))' src/Humanizer/Locales/<code>.yml Prevention
- Prefer age as a scalar unless you need templating.
- If mapping, include only 'template'.
- Build to confirm.
When it happens
Trigger: Authoring 'age:' as a mapping with keys other than template (or no keys at all), instead of a scalar or a { template: ... } block.
Common situations: Author tries to add extra metadata under age; mistyped the template key; left age: {} as a stub.
Related errors
- Phrase '{path}' must define forms.
- Phrase '{path}' must define 'numeric', 'text', or 'words'.
- Template '{path}' must define a scalar 'value'.
- 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/9fe50d45748eff90.
Report an issue: GitHub.