twigphp/Twig · error · LogicException

Unable to register extension

Error message

Unable to register extension "%s" as it is already registered.

What it means

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.

Solutions

  1. Remove the duplicate addExtension call — check whether your framework/bundle already registers the extension automatically.
  2. Deduplicate the extension list before setExtensions(), e.g. by class name.
  3. Register the extension in exactly one place (config OR code), not both.

Example fix

// before
$twig->addExtension(new IntlExtension());
$config['extensions'][] = new IntlExtension(); // registered again
foreach ($config['extensions'] as $ext) { $twig->addExtension($ext); }

// after
$twig->addExtension(new IntlExtension());
$extensions = [];
foreach ($config['extensions'] as $ext) {
    if (!$ext instanceof IntlExtension) { $extensions[] = $ext; }
}
foreach ($extensions as $ext) { $twig->addExtension($ext); }
Defensive patterns

Strategy: validation

Validate before calling

function addExtensionOnce(\Twig\Environment $twig, \Twig\ExtensionInterface $ext): void {
    static $added = [];
    $class = $ext::class;
    if (!in_array($class, $added, true)) { $twig->addExtension($ext); $added[] = $class; }
}

Try / catch

try { $twig->addExtension($ext); } catch (\LogicException $e) {
    if (str_contains($e->getMessage(), 'already registered')) { /* idempotent skip */ }
    else { throw $e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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/51b017c767cb25b4. Report an issue: GitHub.

Appendix: source

Thrown at src/ExtensionSet.php:160

        }

        return $this->lastModified = $lastModified;
    }

    public function addExtension(ExtensionInterface $extension): void
    {
        if ($extension instanceof AttributeExtension) {
            $class = $extension->getClass();
        } else {
            $class = $extension::class;
        }

        if ($this->initialized) {
            throw new \LogicException(\sprintf('Unable to register extension "%s" as extensions have already been initialized.', $class));
        }

        if (isset($this->extensions[$class])) {
            throw new \LogicException(\sprintf('Unable to register extension "%s" as it is already registered.', $class));
        }

        $this->extensions[$class] = $extension;
    }

    public function addFunction(TwigFunction $function): void
    {
        if ($this->initialized) {
            throw new \LogicException(\sprintf('Unable to add function "%s" as extensions have already been initialized.', $function->getName()));
        }

        $this->staging->addFunction($function);
    }

    /**
     * @return TwigFunction[]
     */
    public function getFunctions(): array

View on GitHub (pinned to a414c3a491)