twigphp/Twig · error · InvalidArgumentException

Optimizer mode " " is not valid.

Error message

Optimizer mode "%s" is not valid.

What it means

OptimizerNodeVisitor's constructor validates that the $optimizers bitmask contains no bits beyond the known modes OPTIMIZE_FOR, OPTIMIZE_RAW_FILTER, and OPTIMIZE_TEXT_NODES. Passing a larger integer is an InvalidArgumentException because the mode flag is unknown to this Twig version. Note that -1 (the default, meaning "all") and any combination of valid bits are accepted.

Solutions

  1. Use the class constants only: new OptimizerNodeVisitor(OptimizerNodeVisitor::OPTIMIZE_FOR | OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES).
  2. Pass -1 (or no argument) to enable all optimizations.
  3. Remove stale constant values from Twig 1.x/2.x configs; OPTIMIZE_RAW_FILTER is deprecated (3.11) and other numeric values no longer match.
  4. Validate any config-sourced integer against the valid bitmask before constructing.

Example fix

// before
$env->addNodeVisitor(new \Twig\NodeVisitor\OptimizerNodeVisitor(7));
// after
$env->addNodeVisitor(new \Twig\NodeVisitor\OptimizerNodeVisitor(
    \Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR
    | \Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES
));
Defensive patterns

Strategy: validation

Validate before calling

$valid = -1 | OptimizerNodeVisitor::OPTIMIZE_FOR | OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER | OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES;
$mask = OptimizerNodeVisitor::OPTIMIZE_FOR | OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER | OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES;
if ($mode !== -1 && ($mode < 0 || $mode > $mask)) {
    throw new \InvalidArgumentException("Invalid optimizer mode: $mode");
}

Try / catch

try {
    $visitor = new OptimizerNodeVisitor($mode);
} catch (\InvalidArgumentException $e) {
    $visitor = new OptimizerNodeVisitor(); // fall back to default (all)
}

Prevention

When it happens

Trigger: new OptimizerNodeVisitor(4) or any value greater than OPTIMIZE_FOR|OPTIMIZE_RAW_FILTER|OPTIMIZE_TEXT_NODES (currently 1|4|8 = 13, so >=14 invalid); passing flags copied from another library or hand-invented bit values; passing 2 in newer Twig where OPTIMIZE_RAW_FILTER was removed from valid composition.

Common situations: Custom Twig environment factory configuring the optimizer with an invalid bitmask literal (e.g. old constant values from Twig 1.x); copy-pasted configuration from another optimizer library; a config file value cast into the constructor without validation.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/NodeVisitor/OptimizerNodeVisitor.php:58

final class OptimizerNodeVisitor implements NodeVisitorInterface
{
    public const OPTIMIZE_ALL = -1;
    public const OPTIMIZE_NONE = 0;
    public const OPTIMIZE_FOR = 2;
    public const OPTIMIZE_RAW_FILTER = 4;
    public const OPTIMIZE_TEXT_NODES = 8;

    private $loops = [];
    private $loopsTargets = [];

    /**
     * @param int $optimizers The optimizer mode
     */
    public function __construct(
        private int $optimizers = -1,
    ) {
        if ($optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_TEXT_NODES)) {
            throw new \InvalidArgumentException(\sprintf('Optimizer mode "%s" is not valid.', $optimizers));
        }

        if (-1 !== $optimizers && self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $optimizers)) {
            trigger_deprecation('twig/twig', '3.11', 'The "Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER" option is deprecated and does nothing.');
        }

        if (-1 !== $optimizers && self::OPTIMIZE_TEXT_NODES === (self::OPTIMIZE_TEXT_NODES & $optimizers)) {
            trigger_deprecation('twig/twig', '3.12', 'The "Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES" option is deprecated and does nothing.');
        }
    }

    public function enterNode(Node $node, Environment $env): Node
    {
        if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
            $this->enterOptimizeFor($node);
        }

        return $node;

View on GitHub (pinned to a414c3a491)