twigphp/Twig · error · SyntaxError

You cannot assign a value to

Error message

You cannot assign a value to "%s".

What it means

TempNameExpression reserves identifiers for Twig's internal temporary variables and rejects using the reserved boolean/null literals (true, false, none, null) as assignment targets. This compile-time check prevents users from shadowing values Twig's expression parser treats specially.

Solutions

  1. Rename the variable to something other than true/false/none/null
  2. If generating templates, sanitize variable names against the reserved list ['true','false','none','null']

Example fix

// before
{% set none = value %}
// after
{% set noValue = value %}
Defensive patterns

Strategy: validation

Validate before calling

$reserved = ['true','false','none','null'];
if (in_array(strtolower($name), $reserved, true)) {
    throw new InvalidArgumentException("Cannot use reserved name '$name' as variable");
}

Type guard

function isReservedTwigName(string $name): bool {
    return in_array(strtolower($name), ['true','false','none','null'], true);
}

Try / catch

try {
    $twig->parse($twig->tokenize(new \Twig\Source($code, $name)));
} catch (\Twig\Error\SyntaxError $e) {
    // handle reserved-name assignment
}

Prevention

When it happens

Trigger: Writing {% set true = x %}, {% set null = 1 %} or capturing a for-loop target named 'none' — any assignment whose name lowercases to true/false/none/null.

Common situations: Mistakenly setting a variable named after a literal; template translation or code-generation output that emits reserved words as variable names.

Related errors


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

Appendix: source

Thrown at src/Node/Expression/TempNameExpression.php:32

use Twig\Compiler;
use Twig\Error\SyntaxError;

class TempNameExpression extends AbstractExpression
{
    // 4.0: re-evaluate "varargs" here once the implicit macro varargs bucket is removed
    // (see MacroNode::VARARGS_NAME); the other names map to compiled variables ($context,
    // $macros, $blocks, $this) and must stay.
    public const RESERVED_NAMES = ['varargs', 'context', 'macros', 'blocks', 'this'];

    // Prefix applied to reserved names so their compiled PHP variables cannot clash
    // with the internal ones ($varargs, $context, $macros, $blocks, $this)
    public const RESERVED_NAME_PREFIX = "\u{035C}";

    public function __construct(string|int|null $name, int $lineno)
    {
        // All names supported by ExpressionParser::parsePrimaryExpression() should be excluded
        if ($name && \in_array(strtolower($name), ['true', 'false', 'none', 'null'], true)) {
            throw new SyntaxError(\sprintf('You cannot assign a value to "%s".', $name), $lineno);
        }

        if (self::class === static::class) {
            trigger_deprecation('twig/twig', '3.15', 'The "%s" class is deprecated.', self::class);
        }

        if (null !== $name && (\is_int($name) || ctype_digit($name))) {
            $name = (int) $name;
        } elseif (\in_array($name, self::RESERVED_NAMES, true)) {
            $name = self::RESERVED_NAME_PREFIX.$name;
        }

        parent::__construct([], ['name' => $name], $lineno);
    }

    public function compile(Compiler $compiler): void
    {
        if (null === $this->getAttribute('name')) {

View on GitHub (pinned to a414c3a491)