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
- Use the class constants only: new OptimizerNodeVisitor(OptimizerNodeVisitor::OPTIMIZE_FOR | OptimizerNodeVisitor::OPTIMIZE_TEXT_NODES).
- Pass -1 (or no argument) to enable all optimizations.
- 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.
- 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
- Only compose the mode from the class's own constants, never raw integers.
- Use -1 or omit the argument to enable all optimizations.
- Audit configs migrated from Twig 1.x/2.x for stale constant values.
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
- Invalid escaping strategy
- Locale " " is not supported.
- A block chain requires at least one template.
- Operators with more than 2 operands are not supported yet…
- Unknown " " configuration.
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)