twigphp/Twig · error · SyntaxError
When using set, you must have the same number of variables…
Error message
When using set, you must have the same number of variables and assignments.
What it means
A compile-time SyntaxError raised in SetTokenParser::parse: this is a generic arity-validation guard inside the parser. When a {% set %} tag assigns to multiple targets (e.g. {% set a, b = ... %}), the parser checks that the number of assignment targets equals the number of value expressions; the error fires when a template author writes mismatched counts, such as two variables but only one value expression, so Twig cannot pair each variable with its value.
Solutions
- Make the target list and value list the same length, e.g. '{% set a, b = 1, 2 %}'
- Assign a single array to one variable and index it afterwards if counts differ
- Use capture syntax ({% set a %}...{% endset %}) only for single targets
Example fix
// before
{% set firstName, lastName = user.fullName %}
// after
{% set firstName, lastName = user.firstName, user.lastName %} Defensive patterns
Strategy: validation
Validate before calling
// Count targets vs values in set-with-= statements
if (preg_match('/\{%\s*set\s+([^=}%]+)\s*=\s*(.+?)\s*%}/', $src, $m)) {
$targets = count(array_map('trim', explode(',', $m[1])));
$values = preg_match_all('/(?<![|\w])(?:[\'\"].*?[\'\"]|\w+(?:\([^)]*\))?)/', $m[2]);
if ($targets !== $values) {
throw new InvalidArgumentException('set targets and values must match in count.');
}
} Try / catch
try {
$twig->render($template, $ctx);
} catch (SyntaxError $e) {
if (str_contains($e->getMessage(), 'same number of variables and assignments')) {
// surface authoring error back to template editor
}
throw $e;
} Prevention
- Whenever you add/remove a variable in a multi-set, update the right-hand side in the same commit
- Prefer single-variable sets and destructuring via |split or array destructuring patterns
- Lint templates before deployment
When it happens
Trigger: Writing '{% set a, b = [1] %}' (2 targets, 1 value) or '{% set a = 1, 2 %}' (1 target, 2 values); parse throws after comparing count($names) with count($values).
Common situations: Refactoring a set to add or remove a variable without updating the right-hand side; assuming array elements spread across multiple targets automatically.
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
- When using set with a block, you cannot have a multi-target.
- Unexpected character
- The variadic argument
- The variadic argument
- The template references in a "use" statement must be a…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/8a07355a5746cb3b.
Report an issue: GitHub.
Appendix: source
Thrown at src/TokenParser/SetTokenParser.php:47
*
* @internal
*/
final class SetTokenParser extends AbstractTokenParser
{
public function parse(Token $token): Node
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
$names = $this->parseAssignmentExpression();
$capture = false;
if ($stream->nextIf(Token::OPERATOR_TYPE, '=')) {
$values = $this->parseMultitargetExpression();
$stream->expect(Token::BLOCK_END_TYPE);
if (\count($names) !== \count($values)) {
throw new SyntaxError('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
}
} else {
$capture = true;
if (\count($names) > 1) {
throw new SyntaxError('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
}
$stream->expect(Token::BLOCK_END_TYPE);
$values = $this->parser->subparse([$this, 'decideBlockEnd'], true);
$stream->expect(Token::BLOCK_END_TYPE);
}
return new SetNode($capture, $names, $values, $lineno);
}
public function decideBlockEnd(Token $token): boolView on GitHub (pinned to a414c3a491)