twigphp/Twig · error · SyntaxError
Unclosed comment.
Error message
Unclosed comment.
What it means
A `{# ... #}` comment (or `#{ ... #}` documentation comment) was opened but the Lexer could not find its closing `#}` before end of file. lexComment runs the comment-terminating regex; failure means the comment never terminates.
Solutions
- Locate the `{#` at the reported line and add the closing `#}`.
- Delete abandoned debug comments before committing.
- Remember Twig comments do not nest — remove inner `{#`/`#}` pairs when commenting out blocks that already contain comments.
- Add a pre-commit/CI check that parses templates to catch unclosed comments early.
Example fix
// before
{# TODO: revisit this section
<div>...</div>
// after
{# TODO: revisit this section #}
<div>...</div> Defensive patterns
Strategy: validation
Validate before calling
if (substr_count($code, '{#') !== substr_count($code, '#}')) {
throw new \InvalidArgumentException('Unbalanced comment markers');
} Try / catch
try {
$twig->parse(new \Twig\Source($code, $name));
} catch (\Twig\Error\SyntaxError $e) {
log('Unclosed comment at line '.$e->getTemplateLine());
} Prevention
- Remember Twig comments do not nest — strip inner {#/#} when commenting out blocks.
- Delete debug comments before committing.
- Use an editor plugin that highlights comment regions.
When it happens
Trigger: A template contains `{#` with no matching `#}`, e.g. `{# TODO fix this` left in a template, or a comment whose closer was consumed by nested content like `{# a {# b #}`.
Common situations: Developers leaving debug notes and forgetting to close them; commenting out large template sections where an inner `#}` prematurely ends things then leaves the real content unclosed; comments truncated by file edits.
Related errors
- Unclosed " ".
- Unexpected character
- Unexpected end of file: Unclosed "verbatim" block.
- 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/2a3cd3333e7e1c92.
Report an issue: GitHub.
Appendix: source
Thrown at src/Lexer.php:513
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");
}
}
$this->pushToken(Token::TEXT_TYPE, $this->normalizeNewlines($text), $offset);
}
private function lexComment(bool $isDocumentation = false): void
{
$regex = $isDocumentation ? 'lex_documentation_comment' : 'lex_comment';
if (!preg_match($this->regexes[$regex], $this->code, $match, \PREG_OFFSET_CAPTURE, $this->cursor)) {
throw new SyntaxError('Unclosed comment.', $this->lineno, $this->source);
}
$comment = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
if ($isDocumentation) {
$documentation = $comment;
// support a symmetric "##}" closing marker
if (str_ends_with($documentation, '#')) {
$documentation = substr($documentation, 0, -1);
}
$this->addDocumentation($documentation);
}
$this->moveCursor($comment.$match[0][0]);
}
private function lexString(): void
{
if (preg_match($this->regexes['interpolation_start'], $this->code, $match, 0, $this->cursor)) {View on GitHub (pinned to a414c3a491)