{"record":{"id":"250e7dcaf2f9b76d","repo":"twigphp/Twig","slug":"unable-to-register-extension-s-as-extensions-have-already","errorCode":null,"errorMessage":"Unable to register extension \"%s\" as extensions have already been initialized.","messagePattern":"Unable to register extension \"(.+?)\" as extensions have already been initialized\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/ExtensionSet.php","lineNumber":156,"sourceCode":"                if (is_file($r->getFileName())) {\n                    $lastModified = max(filemtime($r->getFileName()), $lastModified);\n                }\n            }\n        }\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","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/ExtensionSet.php#L138-L174","documentation":"ExtensionSet only accepts new extensions while the environment is uninitialized. Once extensions have been initialized (lazily, usually on first render/load), the set of functions, filters, tags and tests is frozen; calling addExtension afterward throws this LogicException because the compiled/cached state already reflects the old extension set.","triggerScenarios":"Calling $twig->addExtension(...) after Twig has already initialized extensions — typically after the first render(), loadTemplate(), or token parse in the same request; also via setExtensions() late in the lifecycle.","commonSituations":"Registering extensions inside a controller/event handler that runs after some earlier code already rendered a template; Symfony apps calling addExtension after the Twig service was first used; test suites reusing an Environment across tests and adding extensions per-test.","solutions":["Register all extensions immediately after creating the Environment, before any render/load call.","Ensure testMultipleRegistrations-style setup runs once at bootstrap, not per render.","Create a fresh Environment instance if you genuinely need a different extension set at runtime.","If lazy, force extension registration into the service factory that builds the Twig environment."],"exampleFix":"// before\n$twig = new \\Twig\\Environment($loader);\necho $twig->render('hi.twig');\n$twig->addExtension(new MyExtension()); // too late\n\n// after\n$twig = new \\Twig\\Environment($loader);\n$twig->addExtension(new MyExtension());\necho $twig->render('hi.twig');","handlingStrategy":"try-catch","validationCode":"// register early: do this only if extensions are not yet initialized\nif (!$env->hasExtension('Twig\\Extension\\CoreExtension') || !method_exists($env, 'render') || true) {\n    // best guard: add extensions immediately after construction, before first render\n}","typeGuard":null,"tryCatchPattern":"try { $twig->addExtension($ext); } catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'already been initialized')) {\n        $twig = new \\Twig\\Environment($loader, $options);\n        $twig->addExtension($ext); // rebuild environment\n    } else { throw $e; }\n}","preventionTips":["Register every extension immediately after constructing the Environment.","Never render/load templates before extension setup completes.","In frameworks, use the official extension-registration mechanism (bundles/services).","In tests, create a fresh Environment per test instead of mutating shared ones."],"tags":["twig","extension","initialization-order","lifecycle"],"backgroundTag":"invalid-state-transition","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"}