twigphp/Twig · error · SyntaxError

Multiple extends tags are forbidden.

Error message

Multiple extends tags are forbidden.

What it means

Parser::setParent records the template's parent from {% extends %}; if a parent was already set and $throwOnMultiple is true, a second extends tag is rejected with this SyntaxError. Inheritance must resolve to exactly one parent template.

Solutions

  1. Use a single extends with a ternary: {% extends condition ? 'a.html.twig' : 'b.html.twig' %}
  2. Delete the duplicate/leftover extends tag
  3. Compute the parent in the controller/render call and pass it, keeping one extends with a variable: {% extends parent_template %}

Example fix

// before
{% if admin %}{% extends 'admin_base.html' %}{% else %}{% extends 'base.html' %}{% endif %}
// after
{% extends admin ? 'admin_base.html' : 'base.html' %}
Defensive patterns

Strategy: validation

Validate before calling

$n = preg_match_all('/{%-?\\s*extends\\b/', $tpl); if ($n > 1) { /* use one extends with ternary */ }

Try / catch

try { $env->render($name); } catch (\Twig\Error\SyntaxError $e) { if (str_contains($e->getMessage(), 'Multiple extends')) { /* fix template */ } }

Prevention

When it happens

Trigger: Two {% extends %} tags in one template (setParent called twice via getParser with throwOnMultiple=true); the legacy {% extends %} combined with an {% extends %} added by another extension or wrapper.

Common situations: Conditional inheritance attempts ({% if x %}{% extends 'a' %}{% else %}{% extends 'b' %}{% endif %}) — Twig parses both branches; template concatenation/merging; dynamic parent chosen with multiple extends statements instead of one expression.

Understand the failure class

Related errors


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

Appendix: source

Thrown at src/Parser.php:466

        return $this->parent || 0 < \count($this->traits);
    }

    public function setParent(?Node $parent, bool $throwOnMultiple = true): void
    {
        if (null === $parent) {
            trigger_deprecation('twig/twig', '3.12', 'Passing "null" to "%s()" is deprecated.', __METHOD__);
        }

        if (null !== $parent && !$parent instanceof AbstractExpression) {
            trigger_deprecation('twig/twig', '3.24', 'Passing a "%s" instance to "%s()" is deprecated, pass an "AbstractExpression" instance instead.', $parent::class, __METHOD__);
        }

        if (null !== $this->parent) {
            if (!$throwOnMultiple) {
                return;
            }

            throw new SyntaxError('Multiple extends tags are forbidden.', $parent->getTemplateLine(), $parent->getSourceContext());
        }

        $this->parent = $parent;
    }

    public function getStream(): TokenStream
    {
        return $this->stream;
    }

    public function getCurrentToken(): Token
    {
        return $this->stream->getCurrent();
    }

    public function getFunction(string $name, int $line): TwigFunction
    {
        try {

View on GitHub (pinned to a414c3a491)