twigphp/Twig · error · SyntaxError
A block must start with a tag name.
Error message
A block must start with a tag name.
What it means
After a {% token start, the parser expects an identifier (the tag name such as if, block, extends). If the next token is not a NAME_TYPE token, Parser::subparse throws this SyntaxError because there is no valid Twig tag to dispatch to.
Solutions
- Fix the tag so it starts with a valid tag name after {%
- Wrap literal {{ or {% sequences in {% raw %} ... {% endraw %} (or {% verbatim %})
- Check for stray/mismatched {% delimiters from string interpolation or JS templating
- If generating templates, validate that every {% is followed by an identifier
Example fix
// before
{% 123 %}
// after
{% if page == 123 %}...{% endif %} Defensive patterns
Strategy: validation
Validate before calling
if (preg_match('/{%(?!\\s*[a-zA-Z_][a-zA-Z0-9_]*)[^%]*%}/', $tpl)) { /* tag does not start with a name */ } Try / catch
try { $env->render($name); } catch (\Twig\Error\SyntaxError $e) { if (str_contains($e->getMessage(), 'block must start with')) { /* malformed tag */ } } Prevention
- Always put a tag name right after {%
- Wrap literal {{/{% content in {% raw %} blocks
- Lint templates in CI before deployment
When it happens
Trigger: Typing an invalid tag start like {% 123 %}, {% "foo" %}, {% %}, or {% $var %}; unescaped stray braces that begin a block; broken operators such as {% == x %}.
Common situations: Typos in templates; JavaScript or CSS containing {{/{% sequences not wrapped in {% raw %} or {% verbatim %}; templating a language whose syntax collides with Twig delimiters; generation bugs producing empty tag bodies.
Related errors
- Unknown " " configuration.
- The " " modifier takes exactly one argument (0 given).
- The " " modifier takes exactly one argument (2 given).
- An exception has been thrown during the compilation of a…
- Calling the "parent" function outside of a block is…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/96c2402b3f0a3b05.
Report an issue: GitHub.
Appendix: source
Thrown at src/Parser.php:201
$token = $this->stream->next();
$rv[] = new TextNode($token->getValue(), $token->getLine());
break;
case $this->stream->getCurrent()->test(Token::VAR_START_TYPE):
$token = $this->stream->next();
$expr = $this->parseExpression();
$this->stream->expect(Token::VAR_END_TYPE);
$node = new PrintNode($expr, $token->getLine());
NodeDocumentation::add($node, $token);
$rv[] = $node;
break;
case $this->stream->getCurrent()->test(Token::BLOCK_START_TYPE):
$startToken = $this->stream->next();
$token = $this->getCurrentToken();
if (!$token->test(Token::NAME_TYPE)) {
throw new SyntaxError('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext());
}
if (null !== $test && $test($token)) {
if ($dropNeedle) {
$this->stream->next();
}
if (1 === \count($rv)) {
return $rv[0];
}
return new Nodes($rv, $lineno);
}
if (!$subparser = $this->env->getTokenParser($token->getValue())) {
if (null !== $test) {
$e = new SyntaxError(\sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
View on GitHub (pinned to a414c3a491)