{"record":{"id":"1eb809b513a00996","repo":"twigphp/Twig","slug":"argument-s-is-defined-twice-for-macro-s","errorCode":null,"errorMessage":"Argument \"%s\" is defined twice for macro \"%s\".","messagePattern":"Argument \"(.+?)\" is defined twice for macro \"(.+?)\"\\.","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/Node/MacroNode.php","lineNumber":71,"sourceCode":"\n            $args = new ArrayExpression([], $arguments->getTemplateLine());\n            foreach ($arguments as $n => $default) {\n                $args->addElement($default, new LocalVariable($n, $default->getTemplateLine()));\n            }\n            $arguments = $args;\n        }\n\n        $seen = [];\n        foreach ($arguments->getKeyValuePairs() as $pair) {\n            $argName = $pair['key']->getAttribute('name');\n            if (TempNameExpression::RESERVED_NAME_PREFIX.self::VARARGS_NAME === $argName) {\n                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());\n            }\n            if (null !== $variadicName && $variadicName === $this->stripReservedPrefix($argName)) {\n                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());\n            }\n            if (isset($seen[$argName])) {\n                throw new SyntaxError(\\sprintf('Argument \"%s\" is defined twice for macro \"%s\".', $this->stripReservedPrefix($argName), $name), $pair['value']->getTemplateLine(), $pair['value']->getSourceContext());\n            }\n            $seen[$argName] = true;\n        }\n\n        parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name, 'variadic_name' => $variadicName], $lineno);\n    }\n\n    public function compile(Compiler $compiler): void\n    {\n        // 4.0 cleanup: only an explicitly declared variadic (\"...name\") gets a trailing\n        // \"...$bucket\" parameter and a context entry; a non-variadic macro must NOT emit\n        // \"...$varargs\" anymore (so extra arguments raise an error), and the implicit\n        // \"varargs\" context entry and VARARGS_NAME handling below go away.\n        $variadicName = $this->getAttribute('variadic_name');\n        if (null === $variadicName) {\n            // Legacy implicit \"varargs\" bucket: to be removed in 4.0.\n            $bucketName = self::VARARGS_NAME;\n            $bucketVar = self::VARARGS_NAME;","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Node/MacroNode.php#L53-L89","documentation":"MacroNode's constructor builds the argument node for a macro definition and is a generic duplicate-detection guard: while iterating the macro's declared argument names it tracks already-seen names, and this SyntaxError fires at template compile time when the same argument name is declared more than once in a macro signature (e.g. {% macro foo(a, a) %}), which would make the generated argument array ambiguous. The input at fault is the macro's argument list in the template source.","triggerScenarios":"{% macro greet(name, name) %} or the same argument emitted twice by generated templates.","commonSituations":"Merging macro signatures during refactoring; template generators concatenating argument lists without de-duplication.","solutions":["Remove or rename the duplicated macro argument","Deduplicate argument lists in template-generation code before emitting the macro"],"exampleFix":"// before\n{% macro greet(name, name) %}...{% endmacro %}\n// after\n{% macro greet(firstName, lastName) %}...{% endmacro %}","handlingStrategy":"validation","validationCode":"$args = ['name', 'name'];\nif (count($args) !== count(array_unique(array_map('strtolower', $args)))) {\n    throw new InvalidArgumentException('Duplicate macro arguments');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $twig->load('macros.html');\n} catch (\\Twig\\Error\\SyntaxError $e) {\n    if (str_contains($e->getMessage(), 'defined twice')) { /* fix macro */ }\n}","preventionTips":["De-duplicate argument lists in code that generates macros","Keep macro definitions in one reviewed file","Compile all templates as a smoke test in CI"],"tags":["twig","macro","duplicate","compile-time"],"backgroundTag":"duplicate-argument","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}