{"record":{"id":"51b017c767cb25b4","repo":"twigphp/Twig","slug":"unable-to-register-extension-s-as-it-is-already-registered","errorCode":null,"errorMessage":"Unable to register extension \"%s\" as it is already registered.","messagePattern":"Unable to register extension \"(.+?)\" as it is already registered\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/ExtensionSet.php","lineNumber":160,"sourceCode":"        }\n\n        return $this->lastModified = $lastModified;\n    }\n\n    public function addExtension(ExtensionInterface $extension): void\n    {\n        if ($extension instanceof AttributeExtension) {\n            $class = $extension->getClass();\n        } else {\n            $class = $extension::class;\n        }\n\n        if ($this->initialized) {\n            throw new \\LogicException(\\sprintf('Unable to register extension \"%s\" as extensions have already been initialized.', $class));\n        }\n\n        if (isset($this->extensions[$class])) {\n            throw new \\LogicException(\\sprintf('Unable to register extension \"%s\" as it is already registered.', $class));\n        }\n\n        $this->extensions[$class] = $extension;\n    }\n\n    public function addFunction(TwigFunction $function): void\n    {\n        if ($this->initialized) {\n            throw new \\LogicException(\\sprintf('Unable to add function \"%s\" as extensions have already been initialized.', $function->getName()));\n        }\n\n        $this->staging->addFunction($function);\n    }\n\n    /**\n     * @return TwigFunction[]\n     */\n    public function getFunctions(): array","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/ExtensionSet.php#L142-L178","documentation":"ExtensionSet keys extensions by class name and rejects duplicates. Adding an extension whose class is already registered throws this LogicException so that duplicated function/filter/tag registrations (which would later collide) are caught at registration time.","triggerScenarios":"Calling $twig->addExtension(new SomeExtension()) when an instance of the same class (or equivalent ExtensionInterface wrapper class) is already registered — e.g. the extension added in bootstrap plus again in config, or setExtensions() called with a list containing the same class twice.","commonSituations":"Bundle/config auto-registration adding an extension the app also registers manually; a loop over extensions that includes one already added; frameworks auto-adding DebugExtension while the developer adds it too.","solutions":["Remove the duplicate addExtension call — check whether your framework/bundle already registers the extension automatically.","Deduplicate the extension list before setExtensions(), e.g. by class name.","Register the extension in exactly one place (config OR code), not both."],"exampleFix":"// before\n$twig->addExtension(new IntlExtension());\n$config['extensions'][] = new IntlExtension(); // registered again\nforeach ($config['extensions'] as $ext) { $twig->addExtension($ext); }\n\n// after\n$twig->addExtension(new IntlExtension());\n$extensions = [];\nforeach ($config['extensions'] as $ext) {\n    if (!$ext instanceof IntlExtension) { $extensions[] = $ext; }\n}\nforeach ($extensions as $ext) { $twig->addExtension($ext); }","handlingStrategy":"validation","validationCode":"function addExtensionOnce(\\Twig\\Environment $twig, \\Twig\\ExtensionInterface $ext): void {\n    static $added = [];\n    $class = $ext::class;\n    if (!in_array($class, $added, true)) { $twig->addExtension($ext); $added[] = $class; }\n}","typeGuard":null,"tryCatchPattern":"try { $twig->addExtension($ext); } catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'already registered')) { /* idempotent skip */ }\n    else { throw $e; }\n}","preventionTips":["Register extensions in one canonical place (config or bootstrap), not both.","Check whether your framework already auto-registers the extension.","Deduplicate extension lists by class name before calling setExtensions().","Make registration helpers idempotent so repeated calls are safe."],"tags":["twig","extension","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"}