{"record":{"id":"b5aad4494518810c","repo":"twigphp/Twig","slug":"tag-s-is-already-registered","errorCode":null,"errorMessage":"Tag \"%s\" is already registered.","messagePattern":"Tag \"(.+?)\" is already registered\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/Extension/StagingExtension.php","lineNumber":76,"sourceCode":"    public function getFilters(): array\n    {\n        return $this->filters;\n    }\n\n    public function addNodeVisitor(NodeVisitorInterface $visitor): void\n    {\n        $this->visitors[] = $visitor;\n    }\n\n    public function getNodeVisitors(): array\n    {\n        return $this->visitors;\n    }\n\n    public function addTokenParser(TokenParserInterface $parser): void\n    {\n        if (isset($this->tokenParsers[$parser->getTag()])) {\n            throw new \\LogicException(\\sprintf('Tag \"%s\" is already registered.', $parser->getTag()));\n        }\n\n        $this->tokenParsers[$parser->getTag()] = $parser;\n    }\n\n    public function getTokenParsers(): array\n    {\n        return $this->tokenParsers;\n    }\n\n    public function addTest(TwigTest $test): void\n    {\n        if (isset($this->tests[$test->getName()])) {\n            throw new \\LogicException(\\sprintf('Test \"%s\" is already registered.', $test->getName()));\n        }\n\n        $this->tests[$test->getName()] = $test;\n    }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Extension/StagingExtension.php#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Find which two extensions register the same tag and remove one of the registrations.","Unwrap nested addTokenParser calls so the factory/helper runs only once (guard with a flag or container singleton).","Give your custom tag a unique name distinct from any third-party extension's tags.","If overriding a core/extension tag intentionally is desired, do it before initialization via one registration path only."],"exampleFix":"// before\n$twig->addTokenParser(new MyIfParser());\n$twig->addTokenParser(new MyIfParser()); // duplicate tag 'myif'\n\n// after\nstatic $registered = false;\nif (!$registered) {\n    $twig->addTokenParser(new MyIfParser());\n    $registered = true;\n}","handlingStrategy":"try-catch","validationCode":"$knownTags = array_map(fn($p) => $p->getTag(), $twig->getTokenParsers() ?? []);\nif (in_array($parser->getTag(), $knownTags, true)) { /* skip or rename */ }","typeGuard":null,"tryCatchPattern":"try { $twig->addTokenParser($parser); } catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'is already registered')) { log(\"duplicate tag {$parser->getTag()}, skipping\"); }\n    else { throw $e; }\n}","preventionTips":["Keep an inventory of custom tags across all installed extensions.","Register each token parser exactly once, ideally inside one Extension class.","Avoid loading two third-party extensions that define the same tag.","Use dependency injection singletons for bootstrap code that adds parsers."],"tags":["twig","extension","token-parser","duplicate-registration"],"backgroundTag":"conflicting-config-options","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}