pallets/flask · error · TemplateNotFound
{template}
Error message
{template} What it means
DispatchingJinjaLoader._get_source (the explanatory path) iterates the app then blueprints' jinja_loaders, attempts each, records attempts, calls explain_template_loading_attempts for debugging, and if no loader returned the template it raises TemplateNotFound(template). The message is just the template name; the real diagnostics are in the explained attempts logged before raising.
Solutions
- Verify the template file exists under the app's template_folder (default templates/) or the blueprint's template_folder.
- Enable EXPLAIN_TEMPLATE_LOADING or call explain_template_loading_attempts to see which loaders were tried.
- Correct the template name spelling/case and the path passed to render_template.
- For blueprint templates, set template_folder='templates' on the Blueprint and reference by name only.
Example fix
// before
return render_template('home.htm') # typo
// after
return render_template('home.html') Defensive patterns
Strategy: validation
Validate before calling
from jinja2 import TemplateNotFound
def template_exists(app, name: str) -> bool:
try:
app.jinja_env.get_template(name)
return True
except TemplateNotFound:
return False
Try / catch
try:
return render_template(name)
except TemplateNotFound:
app.logger.error('template %s not found; tried loaders see EXPLAIN_TEMPLATE_LOADING', name)
abort(404) Prevention
- Enable EXPLAIN_TEMPLATE_LOADING in dev to see loaders tried.
- Keep templates under app/templates (and bp/templates) and reference by name only.
- Validate template names against the filesystem in CI.
When it happens
Trigger: render_template('missing.html'); render_template('sub/file.html') where the file is absent; a typo in the template name; templates folder misconfigured; blueprint template folder not set so the template is not found in any loader.
Common situations: Template file deleted or renamed; template_folder path wrong relative to the app root; case-sensitivity mismatch (especially deploying from macOS to Linux); blueprint templates expected under the wrong folder.
Related errors
- A valid Flask application was not obtained from
- Allowed methods must be a list of strings, for example…
- Could not import .
- Could not locate a Flask application. Use the 'flask --app'…
- If an instance path is provided it must be absolute. A…
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/92f2922247de286a.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/templating.py:86
rv: tuple[str, str | None, t.Callable[[], bool] | None] | None
trv: None | (tuple[str, str | None, t.Callable[[], bool] | None]) = None
for srcobj, loader in self._iter_loaders(template):
try:
rv = loader.get_source(environment, template)
if trv is None:
trv = rv
except TemplateNotFound:
rv = None
attempts.append((loader, srcobj, rv))
from .debughelpers import explain_template_loading_attempts
explain_template_loading_attempts(self.app, template, attempts)
if trv is not None:
return trv
raise TemplateNotFound(template)
def _get_source_fast(
self, environment: BaseEnvironment, template: str
) -> tuple[str, str | None, t.Callable[[], bool] | None]:
for _srcobj, loader in self._iter_loaders(template):
try:
return loader.get_source(environment, template)
except TemplateNotFound:
continue
raise TemplateNotFound(template)
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_loaderView on GitHub (pinned to 3596b1ab61)