twigphp/Twig · error · SyntaxError

The block ' ' has already been defined line .

Error message

The block '%s' has already been defined line %d.

What it means

Within one template, block names must be unique. Parser::setBlock throws this SyntaxError when a {% block %} with a name that was already defined is registered, reporting the line of the first definition. Duplicate blocks would make it ambiguous which content overrides the parent.

Solutions

  1. Rename the second block to a unique name
  2. Remove the duplicate block definition
  3. If you need repeated rendering of the same content, use {% include %} or a macro instead of a second block
  4. Uniquify generated block names (e.g. append an index) in code that builds templates

Example fix

// before
{% block title %}A{% endblock %}
{% block title %}B{% endblock %}
// after
{% block title %}A{% endblock %}
{% block subtitle %}B{% endblock %}
Defensive patterns

Strategy: validation

Validate before calling

preg_match_all('/{%-?\\s*block\\s+([a-zA-Z_][a-zA-Z0-9_]*)/', $tpl, $m); if (count($m[1]) !== count(array_unique($m[1]))) { /* duplicate block names */ }

Try / catch

try { $env->render($name); } catch (\Twig\Error\SyntaxError $e) { if (str_contains($e->getMessage(), 'already been defined')) { /* duplicate block */ } }

Prevention

When it happens

Trigger: Defining {% block foo %} twice in the same template; a loop or include pattern that re-declares a block; programmatically building a template body that appends a block whose name already exists.

Common situations: Copy-pasting a block and forgetting to rename it; merging two templates that both define {block sidebar}; generating templates from data where block names are derived unsafely (e.g. from array keys that repeat).

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/e638e557a381f454. Report an issue: GitHub.

Appendix: source

Thrown at src/Parser.php:309

    public function hasBlock(string $name): bool
    {
        trigger_deprecation('twig/twig', '3.12', 'Method "%s()" is deprecated.', __METHOD__);

        return isset($this->blocks[$name]);
    }

    public function getBlock(string $name): Node
    {
        trigger_deprecation('twig/twig', '3.12', 'Method "%s()" is deprecated.', __METHOD__);

        return $this->blocks[$name];
    }

    public function setBlock(string $name, BlockNode $value): void
    {
        if (isset($this->blocks[$name])) {
            throw new SyntaxError(\sprintf("The block '%s' has already been defined line %d.", $name, $this->blocks[$name]->getTemplateLine()), $this->getCurrentToken()->getLine(), $this->blocks[$name]->getSourceContext());
        }

        $this->blocks[$name] = new BodyNode([$value], [], $value->getTemplateLine());
    }

    public function hasMacro(string $name): bool
    {
        trigger_deprecation('twig/twig', '3.12', 'Method "%s()" is deprecated.', __METHOD__);

        return isset($this->macros[$name]);
    }

    public function setDocumentationTarget(Node $node): void
    {
        if (null === $index = array_key_last($this->documentationTargets)) {
            throw new \LogicException('A documentation target can only be set while parsing a tag.');
        }
        if (null !== $this->documentationTargets[$index]) {

View on GitHub (pinned to a414c3a491)