tiangolo/fastapi · error · RuntimeError
Frontend directory ' ' does not exist. Resolved absolute…
Error message
Frontend directory '{directory}' does not exist. Resolved absolute path: '{resolved_absolute_path}' What it means
Raised by `_FrontendStaticFiles.__init__` (fastapi/routing.py:1909) as a RuntimeError when `check_dir` is True and `os.path.isdir(directory)` is False. FastAPI verifies the frontend build directory exists at app-construction time so deployment failures surface immediately rather than as 404s in production. The resolved absolute path is included to make path issues (cwd-relative paths, symlinks) easy to diagnose.
Solutions
- Run the frontend build first (e.g. `npm run build`) so the directory exists, then start the server.
- Use an absolute path: `router.frontend('/', directory=str(Path(__file__).parent.parent / 'dist'))`.
- Verify the path at startup: `Path(directory).resolve().is_dir()` and print it before `frontend(...)`.
- During local dev, rely on `fastapi dev` (sets FASTAPI_ENV=development) which downgrades this to a warning via check_dir='auto'.
Example fix
// before
router.frontend('/', directory='dist') # dist does not exist yet
// after
import subprocess, pathlib
subprocess.check_call(['npm', 'run', 'build'])
router.frontend('/', directory=str(pathlib.Path('dist').resolve())) Defensive patterns
Strategy: validation
Validate before calling
import os, pathlib
directory = pathlib.Path('dist').resolve()
if not directory.is_dir():
raise FileNotFoundError(f'Frontend directory not found: {directory}')
router.frontend('/', directory=str(directory)) Type guard
def frontend_dir_exists(directory: object) -> bool:
import os
return isinstance(directory, (str, os.PathLike)) and os.path.isdir(directory) Try / catch
try:
router.frontend('/', directory='dist')
except RuntimeError as exc:
if 'does not exist' in str(exc):
# build or fix the path, then retry/exit with a clear message
raise SystemExit(f'Build the frontend first: {exc}')
raise Prevention
- Run the frontend build (npm run build) before starting the server.
- Use absolute, resolved paths derived from __file__.
- In CI, assert the directory exists in the deploy step before launching uvicorn.
When it happens
Trigger: Calling `router.frontend('/', directory='dist')` when 'dist' does not exist relative to the process working directory. Deploying before running the frontend build step (`npm run build`) that outputs to 'dist'. Pointing `directory` at a path that is only present in another container/stage. `check_dir` defaults to 'auto' which becomes True unless `FASTAPI_ENV=development`.
Common situations: Running `uvicorn app.main:app` before `npm run build`. Working-directory mismatch: the app is launched from a different folder than where 'dist' lives. Docker multi-stage build that did not copy the build output into the final image. A typo in the directory name.
Related errors
- Frontend fallback file
- A frontend path cannot be empty
- A frontend path must start with '/'
- fallback must be 'auto', 'index.html', '404.html', or None
- No route exists for name
AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11).
Data as JSON: /api/errors/86e6697915ea9fe5.
Report an issue: GitHub.
Appendix: source
Thrown at fastapi/routing.py:1909
warnings.warn(
f"Frontend directory '{directory}' does not exist. "
f"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'",
stacklevel=3,
)
return False
class _FrontendStaticFiles(StaticFiles):
def __init__(
self,
*,
directory: str | os.PathLike[str],
fallback: Literal["auto", "index.html", "404.html"] | None,
check_dir: bool,
) -> None:
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: "View on GitHub (pinned to 3e8d1526d8)