nodejs/node · error · TypeError
macro %r takes no keyword argument %r
Error message
macro %r takes no keyword argument %r
What it means
Raised by Macro._invoke when the macro was declared without catch_kwargs (no **kwargs in its signature) but the caller passed a keyword argument whose name is not a declared parameter. The runtime reports the first offending keyword. The 'caller' special case is handled by error 633; this path covers all other unexpected keyword arguments.
Source
Thrown at tools/inspector_protocol/jinja2/runtime.py:567
# it's important that the order of these arguments does not change
# if not also changed in the compiler's `function_scoping` method.
# the order is caller, keyword arguments, positional arguments!
if self.caller and not found_caller:
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>' % (View on GitHub (pinned to 1b2de5e052)
Solutions
- Add the missing parameter to the macro definition, or add catch_kwargs: {% macro my_macro(name, **kwargs) %}.
- Remove the unexpected keyword from the call site.
- When spreading **payload, sanitize it first: {% set clean = payload|rejectattr_name_not_in_macro %} or filter in Python before render.
- Add defaults in the signature so callers can omit: {% macro my_macro(name, size=10) %}.
Example fix
// before
{% macro button(label) %}<button>{{ label }}</button>{% endmacro %}
{{ button('OK', cls='primary') }}
// after
{% macro button(label, cls='default') %}<button class="{{ cls }}">{{ label }}</button>{% endmacro %}
{{ button('OK', cls='primary') }} Defensive patterns
Strategy: validation
Validate before calling
import inspect, re, pathlib
# parse macro definitions and their call sites; flag kwargs not in the signature
macro_re = re.compile(r'\{%\s*macro\s+(\w+)\(([^)]*)\)\s*%\}')
for p in pathlib.Path('templates').rglob('*.html'):
src = p.read_text()
sigs = {m.group(1): [p.strip().split('=')[0] for p in m.group(2).split(',') if p.strip()]
for m in macro_re.finditer(src)}
# naive check: look for kwarg= in calls and warn if not in sig
for call in re.finditer(r'(\w+)\([^)]*?(\w+)=', src):
name, kw = call.group(1), call.group(2)
if name in sigs and '**' not in src and kw not in sigs[name]:
print(f'{p}: unexpected kwarg {kw} for macro {name}') Type guard
def kwarg_allowed(macro_signature: list, has_catch_kwargs: bool, kw: str) -> bool:
return has_catch_kwargs or kw in macro_signature Try / catch
# template authoring bug; fix the call site or add the parameter
Prevention
- Pin the version of shared macro libraries so signatures do not drift unnoticed.
- Add catch_kwargs to macros meant to receive arbitrary HTML attributes.
- Render every macro with a representative call set in CI.
When it happens
Trigger: Calling {{ my_macro(size=10) }} when my_macro was defined as {% macro my_macro(name) %}. Passing HTML attributes as kwargs to a macro that does not accept **kwargs. Copy-pasting a call site from a different macro signature. Variable kwargs spread via **payload where payload contains keys the macro does not accept.
Common situations: Macro signature changes without updating all call sites. Shared macros called from many templates where some pass options that no longer exist. Jinja2 macros used like function calls by developers expecting Python-style defaults/kwargs.
Related errors
- macro %r was invoked with two values for the special caller
- macro %r takes not more than %d argument(s)
- no items for cycling given
- Tried to call non recursive loop. Maybe you forgot the 'rec
- at least one item has to be provided
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/70c5d94fb3131880.
Report an issue: GitHub.