twigphp/Twig · error · SyntaxError
The argument " " in macro " " cannot be defined because the…
Error message
The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.
What it means
Macro definitions reserve the varargs name (internally a reserved-prefixed identifier) for collecting arbitrary extra arguments. Defining an explicit macro argument with that reserved name is rejected at compile time.
Solutions
- Rename the argument to something other than 'varargs'
- Use the implicit varargs behavior: extra arguments are already available via _varargs inside the macro
- If you need named variadic support, check macro variadic options in your Twig version
Example fix
// before
{% macro input(varargs) %}...{% endmacro %}
// after
{% macro input(attrs) %}...{% endmacro %} Defensive patterns
Strategy: validation
Validate before calling
if (in_array(strtolower($argName), ['varargs'], true)) {
throw new InvalidArgumentException("'varargs' is reserved in macros");
} Try / catch
try {
$twig->load('macros.html');
} catch (\Twig\Error\SyntaxError $e) {
// macro argument problems surface at compile/load time
} Prevention
- Never name macro parameters 'varargs'
- Rely on Twig's built-in extra-argument capture
- Lint macro-heavy templates in CI
When it happens
Trigger: Declaring {% macro foo(varargs) %} (Twig rewrites varargs with the reserved prefix) so the argument key equals TempNameExpression::RESERVED_NAME_PREFIX + 'varargs'.
Common situations: Naming a macro parameter 'varargs' believing it captures extra args like PHP's variadics; migrating code between macro implementations.
Related errors
- You cannot assign a value to
- The variadic argument
- Argument " " is defined twice for macro " ".
- Unknown " " configuration.
- Calling the "parent" function outside of a block is…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/d86daeb5cf15789a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Node/MacroNode.php:65
if (!$body instanceof BodyNode) {
trigger_deprecation('twig/twig', '3.12', \sprintf('Not passing a "%s" instance as the "body" argument of the "%s" constructor is deprecated ("%s" given).', BodyNode::class, static::class, $body::class));
}
if (!$arguments instanceof ArrayExpression) {
trigger_deprecation('twig/twig', '3.15', \sprintf('Not passing a "%s" instance as the "arguments" argument of the "%s" constructor is deprecated ("%s" given).', ArrayExpression::class, static::class, $arguments::class));
$args = new ArrayExpression([], $arguments->getTemplateLine());
foreach ($arguments as $n => $default) {
$args->addElement($default, new LocalVariable($n, $default->getTemplateLine()));
}
$arguments = $args;
}
$seen = [];
foreach ($arguments->getKeyValuePairs() as $pair) {
$argName = $pair['key']->getAttribute('name');
if (TempNameExpression::RESERVED_NAME_PREFIX.self::VARARGS_NAME === $argName) {
throw new SyntaxError(\sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $pair['value']->getTemplateLine(), $pair['value']->getSourceContext());
}
if (null !== $variadicName && $variadicName === $this->stripReservedPrefix($argName)) {
throw new SyntaxError(\sprintf('The variadic argument "%s" in macro "%s" cannot have the same name as another argument.', $variadicName, $name), $pair['value']->getTemplateLine(), $pair['value']->getSourceContext());
}
if (isset($seen[$argName])) {
throw new SyntaxError(\sprintf('Argument "%s" is defined twice for macro "%s".', $this->stripReservedPrefix($argName), $name), $pair['value']->getTemplateLine(), $pair['value']->getSourceContext());
}
$seen[$argName] = true;
}
parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name, 'variadic_name' => $variadicName], $lineno);
}
public function compile(Compiler $compiler): void
{
// 4.0 cleanup: only an explicitly declared variadic ("...name") gets a trailing
// "...$bucket" parameter and a context entry; a non-variadic macro must NOT emit
// "...$varargs" anymore (so extra arguments raise an error), and the implicitView on GitHub (pinned to a414c3a491)