twigphp/Twig · error · LogicException

Tag " " is already registered.

Error message

Tag "%s" is already registered.

What it means

The StagingExtension collects user-registered token parsers before extensions are finalized. Twig throws this LogicException when a token parser is registered for a tag name ({% ... %} keyword) that already has a parser in the staging extension, because two parsers for the same tag make parsing ambiguous.

Solutions

  1. Find which two extensions register the same tag and remove one of the registrations.
  2. Unwrap nested addTokenParser calls so the factory/helper runs only once (guard with a flag or container singleton).
  3. Give your custom tag a unique name distinct from any third-party extension's tags.
  4. If overriding a core/extension tag intentionally is desired, do it before initialization via one registration path only.

Example fix

// before
$twig->addTokenParser(new MyIfParser());
$twig->addTokenParser(new MyIfParser()); // duplicate tag 'myif'

// after
static $registered = false;
if (!$registered) {
    $twig->addTokenParser(new MyIfParser());
    $registered = true;
}
Defensive patterns

Strategy: try-catch

Validate before calling

$knownTags = array_map(fn($p) => $p->getTag(), $twig->getTokenParsers() ?? []);
if (in_array($parser->getTag(), $knownTags, true)) { /* skip or rename */ }

Try / catch

try { $twig->addTokenParser($parser); } catch (\LogicException $e) {
    if (str_contains($e->getMessage(), 'is already registered')) { log("duplicate tag {$parser->getTag()}, skipping"); }
    else { throw $e; }
}

Prevention

When it happens

Trigger: Calling $twig->addTokenParser(...) with a parser whose getTag() equals a previously added one — e.g. adding two extensions that both define the same custom tag, or registering the same extension/parser twice.

Common situations: Loading two third-party Twig extensions that implement the same tag name; accidentally adding an extension both via addExtension and via addTokenParser; duplicate addTokenParser calls in a factory method executed twice.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at src/Extension/StagingExtension.php:76

    public function getFilters(): array
    {
        return $this->filters;
    }

    public function addNodeVisitor(NodeVisitorInterface $visitor): void
    {
        $this->visitors[] = $visitor;
    }

    public function getNodeVisitors(): array
    {
        return $this->visitors;
    }

    public function addTokenParser(TokenParserInterface $parser): void
    {
        if (isset($this->tokenParsers[$parser->getTag()])) {
            throw new \LogicException(\sprintf('Tag "%s" is already registered.', $parser->getTag()));
        }

        $this->tokenParsers[$parser->getTag()] = $parser;
    }

    public function getTokenParsers(): array
    {
        return $this->tokenParsers;
    }

    public function addTest(TwigTest $test): void
    {
        if (isset($this->tests[$test->getName()])) {
            throw new \LogicException(\sprintf('Test "%s" is already registered.', $test->getName()));
        }

        $this->tests[$test->getName()] = $test;
    }

View on GitHub (pinned to a414c3a491)