symfony/symfony · error · InvalidArgumentException
The "strategy" attribute of the "twig.safe_class" tag on "%s
Error message
The "strategy" attribute of the "twig.safe_class" tag on "%s" contains the invalid strategy "%s"; expected one of "%s" or a custom name matching "[a-z][a-z0-9_]*".
What it means
Thrown by `SafeClassPass::normalizeStrategies()` when a strategy value is not one of the built-in strategies (`html`, `js`, `css`, `url`, `html_attr`, `html_attr_relaxed`, `all`) and also does not match the custom-name regex `[a-z][a-z0-9_]*`. This catches typos and invalid custom strategy names before they silently fail to escape.
Source
Thrown at src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/SafeClassPass.php:57
}
private function normalizeStrategies(array $tag, string $id): array
{
$strategies = $tag['strategy'] ?? null;
if (\is_string($strategies)) {
$strategies = [$strategies];
} elseif (!\is_array($strategies) || array_filter($strategies, 'is_string') !== $strategies) {
throw new InvalidArgumentException(\sprintf('The "strategy" attribute of the "twig.safe_class" tag on "%s" must be a string or a list of strings.', $id));
} elseif (!$strategies) {
throw new InvalidArgumentException(\sprintf('The "strategy" attribute of the "twig.safe_class" tag on "%s" must not be empty; use "all" to mark the class safe for every strategy.', $id));
}
foreach ($strategies as $strategy) {
if (\in_array($strategy, self::BUILTIN_STRATEGIES, true)) {
continue;
}
if (!preg_match('/^[a-z][a-z0-9_]*$/D', $strategy)) {
throw new InvalidArgumentException(\sprintf('The "strategy" attribute of the "twig.safe_class" tag on "%s" contains the invalid strategy "%s"; expected one of "%s" or a custom name matching "[a-z][a-z0-9_]*".', $id, $strategy, implode('", "', self::BUILTIN_STRATEGIES)));
}
}
return $strategies;
}
}
View on GitHub (pinned to 698e28026c)
Solutions
- Use a built-in strategy name exactly as listed (`html`, `js`, `css`, `url`, `html_attr`, `html_attr_relaxed`, `all`).
- For a custom strategy, use only lowercase letters, digits, and underscores, starting with a letter (e.g. `my_custom`).
- Correct the typo to the intended built-in name.
Example fix
# before
services:
App\Widget:
tags:
- { name: twig.safe_class, strategy: HTML }
# after
services:
App\Widget:
tags:
- { name: twig.safe_class, strategy: html } Defensive patterns
Strategy: validation
Validate before calling
const BUILTIN = ['html','js','css','url','html_attr','html_attr_relaxed','all'];
foreach ((array) $tag['strategy'] as $strategy) {
if (!in_array($strategy, BUILTIN, true) && !preg_match('/^[a-z][a-z0-9_]*$/D', $strategy)) {
throw new \InvalidArgumentException(sprintf('Invalid strategy "%s"', $strategy));
}
} Type guard
function isValidStrategyName(string $s): bool
{
$builtin = ['html','js','css','url','html_attr','html_attr_relaxed','all'];
return in_array($s, $builtin, true) || (bool) preg_match('/^[a-z][a-z0-9_]*$/D', $s);
} Prevention
- Use lowercase strategy names only.
- Stick to built-in names unless you have a real custom escaper.
- Custom names must match [a-z][a-z0-9_]*.
When it happens
Trigger: Tagging with `twig.safe_class` and a strategy like `HTML` (uppercase), `html-css` (hyphen), ` html` (leading space), or any value with uppercase/special chars. Line 56-57 validates the regex.
Common situations: Using uppercase or mixed-case strategy names. Adding a hyphen or space in a custom strategy. Typo like `htlm`.
Related errors
- The "strategy" attribute of the "twig.safe_class" tag on "%s
- The "strategy" attribute of the "twig.safe_class" tag on "%s
- No twig loaders found. You need to tag at least one loader w
- The class "%s" cannot extend "%s" and use the "#[%s]" attrib
- The class "%s" cannot implement "%s" and use the "#[%s]" att
AI-assisted analysis of symfony/symfony@698e28026c (2026-08-06).
Data as JSON: /api/errors/001d3a65851628da.
Report an issue: GitHub.