nodejs/node · error · TemplateNotFound

{name}

Error message

{name}

What it means

Same logic as error 624 but in PrefixLoader.load - the inner loader's load() raised TemplateNotFound for the local name, and PrefixLoader re-raises it with the original prefixed name so the caller sees the full path. load() differs from get_source() in that it returns a compiled Template object (and caches it).

Source

Thrown at tools/inspector_protocol/jinja2/loaders.py:366

    def get_source(self, environment, template):
        loader, name = self.get_loader(template)
        try:
            return loader.get_source(environment, name)
        except TemplateNotFound:
            # re-raise the exception with the correct filename here.
            # (the one that includes the prefix)
            raise TemplateNotFound(template)

    @internalcode
    def load(self, environment, name, globals=None):
        loader, local_name = self.get_loader(name)
        try:
            return loader.load(environment, local_name, globals)
        except TemplateNotFound:
            # re-raise the exception with the correct filename here.
            # (the one that includes the prefix)
            raise TemplateNotFound(name)

    def list_templates(self):
        result = []
        for prefix, loader in iteritems(self.mapping):
            for template in loader.list_templates():
                result.append(prefix + self.delimiter + template)
        return result


class ChoiceLoader(BaseLoader):
    """This loader works like the `PrefixLoader` just that no prefix is
    specified.  If a template could not be found by one loader the next one
    is tried.

    >>> loader = ChoiceLoader([
    ...     FileSystemLoader('/path/to/user/templates'),
    ...     FileSystemLoader('/path/to/system/templates')
    ... ])

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Set env.auto_reload=True (the default) or clear env.cache after deploying template changes.
  2. Confirm the file exists for the inner loader by calling loader.mapping[prefix].get_source(env, suffix) directly.
  3. If using ModuleLoader under a prefix, regenerate the compiled modules with jinja2-cli or compile_exports.
  4. Check that the suffix uses the inner loader's expected path style.

Example fix

// before
env = Environment(loader=PrefixLoader({'app1': ModuleLoader(mods)}), auto_reload=False)
// after
env = Environment(loader=PrefixLoader({'app1': ModuleLoader(mods)}), auto_reload=True)
# or rebuild the compiled module bundle after template edits
Defensive patterns

Strategy: try-catch

Validate before calling

# verify the inner loader can load() before relying on PrefixLoader
prefix, suffix = name.split(loader.delimiter, 1)
inner = loader.mapping[prefix]
inner.load(env, suffix)  # will raise the underlying TemplateNotFound here

Type guard

def prefix_loadable(loader, env, name: str) -> bool:
    try:
        loader.load(env, name)
        return True
    except Exception:
        return False

Try / catch

from jinja2 import TemplateNotFound
try:
    tpl = env.get_template(name)
except TemplateNotFound:
    env.cache.clear()  # in case of stale auto_reload=False cache
    tpl = env.get_template(name)

Prevention

When it happens

Trigger: env.get_template('app1/missing.html') triggers load(); the prefix 'app1' resolves but the suffix 'missing.html' is not loadable by the inner loader. Bytecode cache stale after the file was renamed. Inner loader is a ModuleLoader whose compiled module is missing.

Common situations: Renaming a template without invalidating Environment's template cache (auto_reload disabled). Mixed loader strategies where some prefixes use precompiled modules that were not rebuilt.

Related errors


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