nodejs/node · error · TemplateRuntimeError

%s (%s; did you forget to quote the callable name?)

Error message

%s (%s; did you forget to quote the callable name?)

What it means

Augmented message produced by fail_for_missing_callable (jinja2 environment.py) when a filter/test/global lookup fails AND the looked-up name is itself an Undefined. The base message names the missing callable; the parenthesized suffix is added because the usual cause is passing an undefined variable (which silently resolves to Undefined) instead of a string literal as the callable name.

Source

Thrown at tools/inspector_protocol/jinja2/environment.py:97

    """Load the extensions from the list and bind it to the environment.
    Returns a dict of instantiated environments.
    """
    result = {}
    for extension in extensions:
        if isinstance(extension, string_types):
            extension = import_string(extension)
        result[extension.identifier] = extension(environment)
    return result


def fail_for_missing_callable(string, name):
    msg = string % name
    if isinstance(name, Undefined):
        try:
            name._fail_with_undefined_error()
        except Exception as e:
            msg = '%s (%s; did you forget to quote the callable name?)' % (msg, e)
    raise TemplateRuntimeError(msg)


def _environment_sanity_check(environment):
    """Perform a sanity check on the environment."""
    assert issubclass(environment.undefined, Undefined), 'undefined must ' \
        'be a subclass of undefined because filters depend on it.'
    assert environment.block_start_string != \
        environment.variable_start_string != \
        environment.comment_start_string, 'block, variable and comment ' \
        'start strings must be different'
    assert environment.newline_sequence in ('\r', '\r\n', '\n'), \
        'newline_sequence set to unknown line ending string.'
    return environment


class Environment(object):
    r"""The core component of Jinja is the `Environment`.  It contains
    important shared variables like configuration, filters, tests,

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Quote the callable name: pass `'upper'` not `upper` (or `env.call_filter('upper', value)`).
  2. If the name must be dynamic, resolve and validate it from a known set before calling.
  3. Check the second %s in the message — it reports the undefined error explaining which name was undefined.

Example fix

# before
f = maybe_missing_var      # undefined
env.call_filter(f, value)
# after
env.call_filter('upper', value)
Defensive patterns

Strategy: validation

Validate before calling

from jinja2 import Undefined
KNOWN_FILTERS = {'upper', 'lower'}
def safe_call_filter(env, name, value):
    if isinstance(name, Undefined) or name not in KNOWN_FILTERS:
        raise ValueError('unknown or unquoted filter name: %r' % name)
    return env.call_filter(name, value)

Type guard

from jinja2 import Undefined
def name_is_literal(name) -> bool:
    return not isinstance(name, Undefined)

Try / catch

try:
    env.call_filter(name, value)
except Exception as e:
    if 'did you forget to quote' in str(e):
        env.call_filter('upper', value)   # use the intended literal name
    else:
        raise

Prevention

When it happens

Trigger: Calling env.call_filter / env.call_test with a name argument that is an Undefined (e.g. a typo'd variable or a missing context var) instead of a quoted string; template code that does `{{ x | somevar }}` where somevar is undefined and resolves to the filter-name slot.

Common situations: Dynamically selecting a filter by a variable that wasn't defined; refactoring that renamed a filter but left a call site referencing the old name through a variable; passing `name` as a Python variable holding Undefined from a broken context.

Related errors


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