Main Ecosystems
HomePython CorePandas ReferenceNumPy ScientificFastAPI & PydanticDjango Enterprise
More Ecosystems
Environment & SetupRequests & HTTPAsyncIO ConcurrencyObject-Oriented OOPPyTorch Deep LearningScikit-Learn MLFlask FrameworkWeb ScrapingDatabase & ORMDevOps & Docker

jinja2.exceptions.TemplateNotFound in Flask

Verified FixPython 3.10+Flask 2.x / 3.x / Jinja2Silo: flask

Quick Fix / Solution Rapide

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

  1. Incorrect Directory Name or Placement: Naming the folder template/ (singular) or placing it inside a nested subpackage rather than alongside the module passed to Flask(__name__).
  2. Case Sensitivity Mismatches: On Linux/macOS production servers, index.HTML and index.html are strictly distinct files, whereas Windows local development often masks casing errors.
  3. Relative Path Traps: Calling render_template('templates/index.html') instead of render_template('index.html') (Flask already prefixes the templates root).
  4. Blueprint Isolation: When using Blueprints with template_folder='templates', Flask by default merges blueprint template folders into a shared namespace. If two blueprints contain an index.html, the first registered blueprint's template will always be selected.

Reproduction Code (MCVE)

Example: Bug Reproduction
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.

Example: Recommended Solution
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.

Example: Alternative Solution
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.