twigphp/Twig · error · LogicException

The environment passed to

Error message

The environment passed to "%s" must be dedicated to it: pass a freshly built environment that has no "%s" registered and has not been used yet.

What it means

Sandbox registers a SandboxExtension into the Environment passed to its constructor. Environments accept each extension only once, so if the Environment already has a SandboxExtension registered or was already used to render/load templates, addExtension() throws a LogicException which Sandbox re-throws with this message (chained as previous exception).

Solutions

  1. Create a fresh Environment dedicated to the Sandbox: new Sandbox(new Environment($loader, $options), $policy).
  2. Remove any pre-registered SandboxExtension / 'sandbox' option from the Environment passed in.
  3. If sandbox checks in normal templates are needed too, use a separate Environment for full Sandbox rendering.

Example fix

// before
$env = new Environment($loader);
$env->addExtension(new SandboxExtension($policy, false));
$sandbox = new Sandbox($env, $policy); // throws: env not dedicated

// after
$sandbox = new Sandbox(new Environment($loader), $policy);
Defensive patterns

Strategy: validation

Validate before calling

// Build a dedicated environment; never reuse an app-wide one
$sandbox = new \Twig\Sandbox\Sandbox(new \Twig\Environment($loader, ['autoescape' => true]), $policy);

Try / catch

try { $sandbox = new \Twig\Sandbox\Sandbox($env, $policy); } catch (\LogicException $e) { if (str_contains($e->getMessage(), 'must be dedicated')) { $sandbox = new \Twig\Sandbox\Sandbox(new \Twig\Environment($loader), $policy); } else { throw $e; } }

Prevention

When it happens

Trigger: new Sandbox($env, $policy) where $env already has SandboxExtension (e.g. via addExtension or the 'sandbox' extension option), or $env previously rendered/loaded any template (non-fresh environment).

Common situations: Sharing one application-wide Environment between normal rendering and a Sandbox instance; constructing two Sandbox objects over the same Environment; reusing an Environment created with sandbox config in twig.yaml.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Sandbox/Sandbox.php:43

 * application environment: the sandbox environment must be dedicated to
 * rendering untrusted templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class Sandbox implements SandboxInterface
{
    public function __construct(
        private Environment $env,
        SecurityPolicyInterface $policy,
    ) {
        if ($policy instanceof SecurityPolicy && !$policy->isStrict()) {
            throw new \LogicException('The sandbox requires a strict security policy, call "setStrict(true)" on a dedicated policy for this sandbox.');
        }

        try {
            $env->addExtension(new SandboxExtension($policy, true));
        } catch (\LogicException $e) {
            throw new \LogicException(\sprintf('The environment passed to "%s" must be dedicated to it: pass a freshly built environment that has no "%s" registered and has not been used yet.', self::class, SandboxExtension::class), 0, $e);
        }
    }

    public function render(string $name, array $context = []): string
    {
        return $this->env->render($name, $context);
    }

    public function display(string $name, array $context = []): void
    {
        $this->env->display($name, $context);
    }

    public function stream(string $name, array $context = []): iterable
    {
        yield from $this->env->load($name)->stream($context);
    }

View on GitHub (pinned to a414c3a491)