Skip to main content

Debugging Template Resolution

When working with complex Flask applications that use multiple blueprints, it can be difficult to determine why a specific template is being loaded or why a TemplateNotFound error is occurring. This project provides a built-in mechanism to explain the template resolution process.

Enable Template Loading Explanation

To see exactly how Flask is searching for your templates, set the EXPLAIN_TEMPLATE_LOADING configuration key to True.

from flask import Flask

app = Flask(__name__)
app.config["EXPLAIN_TEMPLATE_LOADING"] = True

When this is enabled, the DispatchingJinjaLoader in src/flask/templating.py switches from a "fast" search to an "explained" search. Every time a template is rendered, Flask will log the sequence of attempts it made to find that template.

Interpreting the Resolution Log

The logs are sent to the application's logger at the INFO level. A typical log entry for a failed template lookup looks like this:

Locating template 'missing_template.html':
1: trying loader of application 'myapp'
class: jinja2.loaders.FileSystemLoader
searchpath:
- /path/to/myapp/templates
-> no match
2: trying loader of blueprint 'admin' (myapp.apps.admin)
class: jinja2.loaders.FileSystemLoader
searchpath:
- /path/to/myapp/apps/admin/templates
-> no match
Error: the template could not be found.
The template was looked up from an endpoint that belongs to the blueprint 'admin'.
Maybe you did not place a template in the right folder?

The explain_template_loading_attempts function in src/flask/debughelpers.py generates this output by iterating through:

  1. The main application's jinja_loader.
  2. Each registered blueprint's jinja_loader in the order they were registered.

Troubleshooting Common Issues

Missing Logs

If you have enabled EXPLAIN_TEMPLATE_LOADING but do not see any output in your console, check your logger configuration. The explanation is logged using app.logger.info. If your log level is set to WARNING or higher, these messages will be suppressed.

import logging
# Ensure the level is at least INFO
app.logger.setLevel(logging.INFO)

Multiple Matches Warning

If multiple loaders find a match for the same template name, Flask will log a warning: Warning: multiple loaders returned a match for the template.

This often happens when two blueprints define a template with the same name (e.g., layout.html) without namespacing them. Flask will always use the first match it finds based on the registration order.

Blueprint Resolution Order

The DispatchingJinjaLoader._iter_loaders method determines the search order:

# src/flask/templating.py

def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, BaseLoader]]:
loader = self.app.jinja_loader
if loader is not None:
yield self.app, loader

for blueprint in self.app.iter_blueprints():
loader = blueprint.jinja_loader
if loader is not None:
yield blueprint, loader

Because the application loader is checked first, a template in the main templates folder will always override a template with the same name in a blueprint's folder. If you need a blueprint to provide its own version of a template, ensure the main application does not have a conflicting file at the same path.