{"record":{"id":"1ce9732dbede1b19","repo":"twigphp/Twig","slug":"an-escaping-strategy-must-be-a-string-or-false","errorCode":null,"errorMessage":"An escaping strategy must be a string or false.","messagePattern":"An escaping strategy must be a string or false\\.","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/TokenParser/AutoEscapeTokenParser.php","lineNumber":37,"sourceCode":"\n/**\n * Marks a section of a template to be escaped or not.\n *\n * @internal\n */\nfinal class AutoEscapeTokenParser extends AbstractTokenParser\n{\n    public function parse(Token $token): Node\n    {\n        $lineno = $token->getLine();\n        $stream = $this->parser->getStream();\n\n        if ($stream->test(Token::BLOCK_END_TYPE)) {\n            $value = 'html';\n        } else {\n            $expr = $this->parser->parseExpression();\n            if (!$expr instanceof ConstantExpression) {\n                throw new SyntaxError('An escaping strategy must be a string or false.', $stream->getCurrent()->getLine(), $stream->getSourceContext());\n            }\n            $value = $expr->getAttribute('value');\n        }\n\n        $stream->expect(Token::BLOCK_END_TYPE);\n        $body = $this->parser->subparse([$this, 'decideBlockEnd'], true);\n        $stream->expect(Token::BLOCK_END_TYPE);\n\n        return new AutoEscapeNode($value, $body, $lineno);\n    }\n\n    public function decideBlockEnd(Token $token): bool\n    {\n        return $token->test('endautoescape');\n    }\n\n    public function getTag(): string\n    {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/TokenParser/AutoEscapeTokenParser.php#L19-L55","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"{% autoescape strategyName %}...{% endautoescape %}\n\n{# after #}\n{% autoescape 'html' %}...{% endautoescape %}","handlingStrategy":"validation","validationCode":"$allowed = ['html', 'js', 'css', 'url', false];\nif (!in_array($strategy, $allowed, true)) {\n    throw new \\InvalidArgumentException('autoescape strategy must be a literal html|js|css|url|false');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $twig->parse($twig->tokenize(new \\Twig\\Source($code, $name)));\n} catch (\\Twig\\Error\\SyntaxError $e) {\n    if (str_contains($e->getMessage(), 'escaping strategy must be a string')) {\n        // report template line and fix the autoescape argument\n    }\n    throw $e;\n}","preventionTips":["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."],"tags":["twig","autoescape","syntax-error","escaping"],"backgroundTag":"invalid-argument-value","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}