nodejs/node · error · TypeError

macro %r takes not more than %d argument(s)

Error message

macro %r takes not more than %d argument(s)

What it means

Raised by Macro._invoke when the macro does not accept catch_varargs (no *args) and the number of positional arguments supplied exceeds self._argument_count (the number of declared positional parameters). The runtime reports how many arguments the macro actually takes.

Source

Thrown at tools/inspector_protocol/jinja2/runtime.py:572

            caller = kwargs.pop('caller', None)
            if caller is None:
                caller = self._environment.undefined('No caller defined',
                                                     name='caller')
            arguments.append(caller)

        if self.catch_kwargs:
            arguments.append(kwargs)
        elif kwargs:
            if 'caller' in kwargs:
                raise TypeError('macro %r was invoked with two values for '
                                'the special caller argument.  This is '
                                'most likely a bug.' % self.name)
            raise TypeError('macro %r takes no keyword argument %r' %
                            (self.name, next(iter(kwargs))))
        if self.catch_varargs:
            arguments.append(args[self._argument_count:])
        elif len(args) > self._argument_count:
            raise TypeError('macro %r takes not more than %d argument(s)' %
                            (self.name, len(self.arguments)))

        return self._invoke(arguments, autoescape)

    def _invoke(self, arguments, autoescape):
        """This method is being swapped out by the async implementation."""
        rv = self._func(*arguments)
        if autoescape:
            rv = Markup(rv)
        return rv

    def __repr__(self):
        return '<%s %s>' % (
            self.__class__.__name__,
            self.name is None and 'anonymous' or repr(self.name)
        )

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Trim the call to the declared arity, or add parameters/defaults to the macro.
  2. Add catch_varargs: {% macro my_macro(a, *rest) %} if variadic calls are intentional.
  3. Validate the input list length in Python before render: assert len(items) <= expected.
  4. Lock the shared-macro version with a pin and add a regression test for arity.

Example fix

// before
{% macro greet(name) %}Hi {{ name }}{% endmacro %}
{{ greet('Ann', 'Bob') }}
// after
{% macro greet(*names) %}Hi {{ names|join(', ') }}{% endmacro %}
{{ greet('Ann', 'Bob') }}
Defensive patterns

Strategy: validation

Validate before calling

import re, pathlib
macro_re = re.compile(r'\{%\s*macro\s+(\w+)\(([^)]*)\)\s*%\')
for p in pathlib.Path('templates').rglob('*.html'):
    src = p.read_text()
    defs = {m.group(1): m.group(2) for m in macro_re.finditer(src)}
    # check call sites that spread *items
    for call in re.finditer(r'(\w+)\(\*([\w.]+)\)', src):
        name = call.group(1)
        if name in defs and '*' not in defs[name]:
            arity = len([a for a in defs[name].split(',') if a.strip()])
            print(f'{p}: {name}(*{call.group(2)}) - macro takes {arity} positional')

Type guard

def arity_ok(positional_count: int, macro_param_count: int, has_varargs: bool) -> bool:
    return has_varargs or positional_count <= macro_param_count

Try / catch

# arity mismatch is a template bug; fix call site or macro signature

Prevention

When it happens

Trigger: Calling {{ my_macro(1, 2, 3) }} when my_macro is {% macro my_macro(a) %}. Passing a list as positional args via the * form: {{ my_macro(*items) }} where len(items) exceeds the parameter count. Macro refactored to take fewer parameters but call sites unchanged.

Common situations: Removing a macro parameter without updating call sites. Data-driven rendering where the input arity varies but the macro is fixed. Templating helpers imported from a shared library whose signature changed across versions.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/1592bec07a6704fb. Report an issue: GitHub.