twigphp/Twig · error · SyntaxError
An escaping strategy must be a string or false.
Error message
An escaping strategy must be a string or false.
What it means
Thrown by AutoEscapeTokenParser::parse when the {% autoescape %} tag is given an expression that is not a constant string (or false). Twig requires the escaping strategy to be statically known at compile time so it can bake it into the compiled template. Non-constant expressions (variables, function calls) are rejected with a SyntaxError at parse time.
Solutions
- Use a literal string: {% autoescape 'html' %}, 'js', 'css', 'url', or false.
- Move dynamic strategy selection to PHP by pushing a custom Escaper/Guard escaper or setting autoescape as a closure in the Environment options.
- If you only need conditional output handling, render with separate includes per strategy instead of a variable strategy.
- Bare {% autoescape %} defaults to 'html' — omit the argument if html is wanted.
Example fix
{% autoescape strategyName %}...{% endautoescape %}
{# after #}
{% autoescape 'html' %}...{% endautoescape %} Defensive patterns
Strategy: validation
Validate before calling
$allowed = ['html', 'js', 'css', 'url', false];
if (!in_array($strategy, $allowed, true)) {
throw new \InvalidArgumentException('autoescape strategy must be a literal html|js|css|url|false');
} Try / catch
try {
$twig->parse($twig->tokenize(new \Twig\Source($code, $name)));
} catch (\Twig\Error\SyntaxError $e) {
if (str_contains($e->getMessage(), 'escaping strategy must be a string')) {
// report template line and fix the autoescape argument
}
throw $e;
} Prevention
- Only pass literal strings or false to {% autoescape %}.
- Use Environment autoescape option (or a closure) for dynamic strategies.
- Lint templates in CI to catch non-constant autoescape arguments early.
When it happens
Trigger: Writing {% autoescape someVar %} ... {% endautoescape %} or {% autoescape escape_strategy_from_config %} where the argument parses as any expression other than a ConstantExpression (e.g. a name, array, or function call).
Common situations: Trying to make the escaping strategy dynamic based on request/config data; assuming {% autoescape %} accepts a runtime variable; migrating code that computed the strategy in a template instead of at environment setup.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- An exception has been thrown during the compilation of a…
- Calling the "parent" function outside of a block is…
- Calling the "parent" function on a template that does not…
- Unclosed " ".
- Unexpected character
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/1ce9732dbede1b19.
Report an issue: GitHub.
Appendix: source
Thrown at src/TokenParser/AutoEscapeTokenParser.php:37
/**
* Marks a section of a template to be escaped or not.
*
* @internal
*/
final class AutoEscapeTokenParser extends AbstractTokenParser
{
public function parse(Token $token): Node
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
if ($stream->test(Token::BLOCK_END_TYPE)) {
$value = 'html';
} else {
$expr = $this->parser->parseExpression();
if (!$expr instanceof ConstantExpression) {
throw new SyntaxError('An escaping strategy must be a string or false.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
}
$value = $expr->getAttribute('value');
}
$stream->expect(Token::BLOCK_END_TYPE);
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
$stream->expect(Token::BLOCK_END_TYPE);
return new AutoEscapeNode($value, $body, $lineno);
}
public function decideBlockEnd(Token $token): bool
{
return $token->test('endautoescape');
}
public function getTag(): string
{View on GitHub (pinned to a414c3a491)