twigphp/Twig · error · SyntaxError
Unexpected end of file: Unclosed "verbatim" block.
Error message
Unexpected end of file: Unclosed "verbatim" block.
What it means
The Lexer reached end of file while in RAW data state, meaning a `{% verbatim %}` block was opened but its `{% endverbatim %}` tag was never found. lexRawData scans for the closing tag; if the regex fails to match, the block is unclosed.
Solutions
- Add the missing `{% endverbatim %}` before the end of the template.
- Keep verbatim open/close pairs within the same template file — they cannot span includes.
- Search the project for `{% verbatim %}` occurrences and verify each has a counterpart.
- Note Twig 3.x also supports the shorter `{% raw %}` tag; mixing raw/verbatim spellings for open/close is invalid.
Example fix
// before
{% verbatim %}
<div>{{ not_twig }}</div>
// after
{% verbatim %}
<div>{{ not_twig }}</div>
{% endverbatim %} Defensive patterns
Strategy: validation
Validate before calling
if (substr_count($code, '{% verbatim %}') + substr_count($code, '{% raw %}') !==
substr_count($code, '{% endverbatim %}') + substr_count($code, '{% endraw %}')) {
throw new \InvalidArgumentException('Unbalanced verbatim/raw tags');
} Try / catch
try {
$twig->parse(new \Twig\Source($code, $name));
} catch (\Twig\Error\SyntaxError $e) {
log('Unclosed verbatim block: '.$e->getMessage());
} Prevention
- Always keep verbatim/raw open and close tags in the same file.
- Use consistent spelling (raw vs verbatim) for both tags.
- Watch for minifiers stripping {% endraw %} tags.
When it happens
Trigger: A template contains `{% verbatim %}` without a matching `{% endverbatim %}` before EOF, e.g. `{% verbatim %}<div>{{ raw }}</div>` with the end tag accidentally deleted or placed after an `include` boundary.
Common situations: Documenting other template engines inside verbatim blocks and forgetting the closer; conditional includes where the `{% endverbatim %}` lives in a different partial than the opener; minifiers or build steps stripping what looks like a stray tag.
Related errors
- Unclosed " ".
- Unexpected character
- Unclosed comment.
- Unexpected " ".
- The lexer or the parser ended up in an unsupported state.
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/1927ed3c75891eab.
Report an issue: GitHub.
Appendix: source
Thrown at src/Lexer.php:487
while ($i + 1 < $length && ctype_digit($str[$i + 1]) && $str[$i + 1] < '8' && \strlen($octal) < 3) {
$octal .= $str[++$i];
}
$result .= \chr(octdec($octal) % 256);
} else {
trigger_deprecation('twig/twig', '3.12', 'Character "%s" should not be escaped; the "\" character is ignored in Twig 3 but will not be in Twig 4. Please remove the extra "\" character at position %d in "%s" at line %d.', $nextChar, $i + 1, $this->source->getName(), $this->lineno);
$result .= $nextChar;
}
++$i;
}
return $result;
}
private function lexRawData(): void
{
if (!preg_match($this->regexes['lex_raw_data'], $this->code, $match, \PREG_OFFSET_CAPTURE, $this->cursor)) {
throw new SyntaxError('Unexpected end of file: Unclosed "verbatim" block.', $this->lineno, $this->source);
}
$offset = $this->cursor;
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
$this->moveCursor($text.$match[0][0]);
// trim?
if (isset($match[1][0])) {
if ($this->options['whitespace_trim'] === $match[1][0]) {
// whitespace_trim detected ({%-, {{- or {#-)
$text = rtrim($text);
} else {
// whitespace_line_trim detected ({%~, {{~ or {#~)
// don't trim \r and \n
$text = rtrim($text, " \t\0\x0B");
}
}
View on GitHub (pinned to a414c3a491)