twigphp/Twig · error · SyntaxError

Cannot assign to " ", only variables can be assigned in…

Error message

Cannot assign to "%s", only variables can be assigned in object/mapping destructuring.

What it means

Twig's object/mapping destructuring (`{key: var} = value`) only allows variable names (AssignContextVariable nodes) on the receiving side. The constructor validates each key-value pair's value and throws this SyntaxError when a non-variable expression (a constant, function call, etc.) appears as the assignment target.

Solutions

  1. Replace the non-variable target in the destructuring pattern with a plain variable name.
  2. Assign to a variable first, then transform the value in a following expression or statement.
  3. In PHP-generated templates, ensure pair values are AssignContextVariable nodes before constructing ObjectDestructuringSetBinary.

Example fix

// before (template)
{% set {name: user.name} = data %}
// after
{% set {name: userName} = data %}
{% set user = user|merge({name: userName}) %}
Defensive patterns

Strategy: validation

Validate before calling

// Only simple variable identifiers may appear as destructuring targets in Twig.
// In templates, ensure the right side of each `key:` in the pattern is a bare name, e.g. {a: a, b: b}.
// When generating nodes in PHP:
foreach ($pairs as $p) {
    if (!$p['value'] instanceof \Twig\Node\Expression\AssignContextVariable) {
        throw new \InvalidArgumentException('Destructuring target must be a simple variable');
    }
}

Prevention

When it happens

Trigger: Compiling `{ {a: 'literal'} = obj }` or `{ {a: someFn(x)} = obj }`; also direct PHP construction of ObjectDestructuringSetBinary whose left ArrayExpression contains pairs whose value is not an AssignContextVariable. Note the error message interpolates the class name of the offending node, not a template string.

Common situations: Misreading destructuring syntax and trying to assign into an object property or call result; templates generated programmatically with non-variable targets; confusion with JavaScript object destructuring where renaming via `{a: newName}` is valid but Twig requires newName itself to be a simple variable.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/Node/Expression/Binary/ObjectDestructuringSetBinary.php:41

 * @internal
 */
class ObjectDestructuringSetBinary extends AbstractBinary
{
    /** @var list<array{property: string, variable: string}> */
    private array $mappings = [];

    /**
     * @param ArrayExpression    $left  The array expression containing object/mapping destructuring properties
     * @param AbstractExpression $right The expression providing values for assignment
     */
    public function __construct(Node $left, Node $right, int $lineno)
    {
        if (!$left instanceof ArrayExpression) {
            throw new \LogicException('Left side must be ArrayExpression for object/mapping destructuring.');
        }
        foreach ($left->getKeyValuePairs() as $pair) {
            if (!$pair['value'] instanceof AssignContextVariable) {
                throw new SyntaxError(\sprintf('Cannot assign to "%s", only variables can be assigned in object/mapping destructuring.', $pair['value']::class), $lineno);
            }

            $this->mappings[] = [
                'property' => $pair['key']->getAttribute('value'),
                'variable' => $pair['value']->getAttribute('name'),
            ];
        }

        parent::__construct($left, $right, $lineno);
    }

    public function compile(Compiler $compiler): void
    {
        $compiler->addDebugInfo($this);
        $var = '$'.$compiler->getVarName();
        $compiler->raw('[[');
        foreach ($this->mappings as $i => $mapping) {
            if ($i) {

View on GitHub (pinned to a414c3a491)