tiangolo/fastapi · error · RuntimeError
Frontend fallback file '{fallback}' does not exist in direct
Error message
Frontend fallback file '{fallback}' does not exist in directory '{directory}'. Resolved absolute directory: '{resolved_directory}' What it means
At construction time, `_FrontendStaticFiles.__init__` calls `_check_fallback_file` (routing.py:1919-1929) when `check_dir` is true and `fallback` is `"index.html"` or `"404.html"`. It stats the file via `lookup_path`; if missing or not a regular file, it raises `RuntimeError`. This guarantees the configured fallback page actually exists before the app serves traffic.
Source
Thrown at fastapi/routing.py:1925
self.fallback = fallback
if check_dir and not os.path.isdir(directory):
raise RuntimeError(
f"Frontend directory '{directory}' does not exist. "
f"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'"
)
super().__init__(
directory=directory,
html=True,
check_dir=check_dir,
follow_symlink=False,
)
if check_dir and fallback in {"index.html", "404.html"}:
self._check_fallback_file(fallback)
def _check_fallback_file(self, fallback: str) -> None:
_, stat_result = self.lookup_path(fallback)
if stat_result is None or not stat.S_ISREG(stat_result.st_mode):
raise RuntimeError(
f"Frontend fallback file '{fallback}' does not exist in "
f"directory '{self.directory}'. Resolved absolute directory: "
f"'{self._get_resolved_directory()}'"
)
def _get_resolved_directory(self) -> str:
assert self.directory is not None
return _get_resolved_absolute_path(self.directory)
def get_path(self, scope: Scope) -> str:
path = _get_fastapi_scope(scope).get(_FASTAPI_FRONTEND_PATH_KEY, "")
assert isinstance(path, str)
return os.path.normpath(os.path.join(*path.split("/")))
async def get_response_for_scope(self, scope: Scope) -> Response:
if not self.config_checked:
await self.check_config()
self.config_checked = TrueView on GitHub (pinned to 42a41db11f)
Solutions
- Ensure the named fallback file exists directly under `directory` at startup.
- Point `directory` at the folder that actually contains `index.html`/`404.html`.
- Use `fallback="auto"` so FastAPI uses whichever fallback file is present (or none).
- Use `fallback=None` to disable fallback entirely.
Example fix
# before
app.frontend("/", directory="dist", fallback="index.html") # dist/index.html missing
# after
app.frontend("/", directory="dist", fallback="auto") Defensive patterns
Strategy: validation
Validate before calling
import os, stat
from pathlib import Path
def assert_fallback_file(directory: str, fallback: str | None) -> None:
if fallback in {"index.html", "404.html"}:
p = Path(directory) / fallback
if not (p.is_file() and stat.S_ISREG(os.stat(p).st_mode)):
raise FileNotFoundError(f"Fallback file missing: {p}")
# usage
assert_fallback_file(dist, "index.html")
app.frontend("/", directory=dist, fallback="index.html") Type guard
import os
def fallback_file_present(directory: str, fallback: str | None) -> bool:
return fallback in {None, "auto"} or os.path.isfile(os.path.join(directory, fallback)) Prevention
- Prefer `fallback="auto"` unless you specifically require a named file.
- Include fallback files in your build output verification step.
- Point `directory` at the folder that directly contains index.html/404.html.
When it happens
Trigger: `app.frontend("/", directory="dist", fallback="index.html")` when `dist/index.html` does not exist at startup (and check_dir is active). Same for `fallback="404.html"` without `dist/404.html`.
Common situations: Frontend build emits files under a nested folder (e.g. `dist/build/index.html`) but you point at `dist`; SPA that has no 404 page but you force `fallback="404.html"`; building in a different mode that skips index generation.
Related errors
- A frontend path cannot be empty
- Frontend directory '{directory}' does not exist. Resolved ab
- A frontend path must start with '/'
- fallback must be 'auto', 'index.html', '404.html', or None
- Prefix and path cannot be both empty (path operation: {name}
AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04).
Data as JSON: /data/errors/08273329afed413f.json.
Report an issue: GitHub.