jinja2.exceptions.TemplateNotFound in Flask
Place all HTML templates inside a directory named exactly templates/ in the same directory as your Flask application module, or specify Flask(__name__, template_folder='custom_path').
Root Cause Analysis
This error occurs when Python tries to render an HTML document via Jinja2's render_template() loader, but Flask cannot locate the specified file within its registered template directory tree.
Flask Template Discovery Mechanism
By default, Flask searches for templates relative to the application's root path in a subdirectory named templates. Jinja2's FileSystemLoader evaluates paths relative to this folder, not relative to the current working directory (os.getcwd()).
Common Root Causes
- Incorrect Directory Name or Placement: Naming the folder
template/(singular) or placing it inside a nested subpackage rather than alongside the module passed toFlask(__name__). - Case Sensitivity Mismatches: On Linux/macOS production servers,
index.HTMLandindex.htmlare strictly distinct files, whereas Windows local development often masks casing errors. - Relative Path Traps: Calling
render_template('templates/index.html')instead ofrender_template('index.html')(Flask already prefixes the templates root). - Blueprint Isolation: When using Blueprints with
template_folder='templates', Flask by default merges blueprint template folders into a shared namespace. If two blueprints contain anindex.html, the first registered blueprint's template will always be selected.
Reproduction Code (MCVE)
from flask import Flask, render_template
app = Flask(__name__)
with app.app_context():
# Attempting to render a template that does not exist in the default 'templates/' folder
render_template('nonexistent_index.html')
Solution 1: Configure Explicit `template_folder` or Standard Layout
Create the template in the configured templates directory or explicitly pass the absolute template folder path to Flask.
import os
import tempfile
from flask import Flask, render_template
# Simulate standard template directory structure
with tempfile.TemporaryDirectory() as tmpdir:
templates_dir = os.path.join(tmpdir, 'templates')
os.makedirs(templates_dir, exist_ok=True)
index_file = os.path.join(templates_dir, 'dashboard.html')
with open(index_file, 'w', encoding='utf-8') as f:
f.write('<h1>Welcome {{ username }}</h1>')
# Configure Flask with explicit template folder
app = Flask(__name__, template_folder=templates_dir)
with app.app_context():
rendered = render_template('dashboard.html', username='PythonFix User')
print(f'Successfully rendered: {rendered.strip()}')
Solution 2: Use `render_template_string` for Inline String Templates
For dynamic email templates or inline HTML fragments, use render_template_string without filesystem dependencies.
from flask import Flask, render_template_string
app = Flask(__name__)
template_content = '''
<div class="alert alert-success">
<strong>{{ title }}</strong>: {{ message }}
</div>
'''
with app.app_context():
output = render_template_string(
template_content,
title='System Ready',
message='All services operational'
)
print(f'Rendered string template: {output.strip()}')
Common Mistakes & Best Practices
When organizing larger Flask applications with Blueprints, avoid placing template files directly in blueprints/auth/templates/login.html. Instead, namespace blueprint templates using a subfolder: blueprints/auth/templates/auth/login.html and render via render_template('auth/login.html'). This prevents naming collisions where an admin blueprint's login.html accidentally overrides the user blueprint's login.html.
Contrasting TemplateNotFound with FileNotFoundError: FileNotFoundError is a built-in OS error raised when calling open('file.html'), whereas TemplateNotFound is a Jinja2 exception indicating the template was not found within any registered Jinja template loader.