{"id":"08273329afed413f","repo":"tiangolo/fastapi","slug":"frontend-fallback-file-fallback-does-not-exist","errorCode":null,"errorMessage":"Frontend fallback file '{fallback}' does not exist in directory '{directory}'. Resolved absolute directory: '{resolved_directory}'","messagePattern":"Frontend fallback file '(.+?)' does not exist in directory '(.+?)'\\. Resolved absolute directory: '(.+?)'","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"fastapi/routing.py","lineNumber":1925,"sourceCode":"        self.fallback = fallback\n        if check_dir and not os.path.isdir(directory):\n            raise RuntimeError(\n                f\"Frontend directory '{directory}' does not exist. \"\n                f\"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'\"\n            )\n        super().__init__(\n            directory=directory,\n            html=True,\n            check_dir=check_dir,\n            follow_symlink=False,\n        )\n        if check_dir and fallback in {\"index.html\", \"404.html\"}:\n            self._check_fallback_file(fallback)\n\n    def _check_fallback_file(self, fallback: str) -> None:\n        _, stat_result = self.lookup_path(fallback)\n        if stat_result is None or not stat.S_ISREG(stat_result.st_mode):\n            raise RuntimeError(\n                f\"Frontend fallback file '{fallback}' does not exist in \"\n                f\"directory '{self.directory}'. Resolved absolute directory: \"\n                f\"'{self._get_resolved_directory()}'\"\n            )\n\n    def _get_resolved_directory(self) -> str:\n        assert self.directory is not None\n        return _get_resolved_absolute_path(self.directory)\n\n    def get_path(self, scope: Scope) -> str:\n        path = _get_fastapi_scope(scope).get(_FASTAPI_FRONTEND_PATH_KEY, \"\")\n        assert isinstance(path, str)\n        return os.path.normpath(os.path.join(*path.split(\"/\")))\n\n    async def get_response_for_scope(self, scope: Scope) -> Response:\n        if not self.config_checked:\n            await self.check_config()\n            self.config_checked = True","sourceCodeStart":1907,"sourceCodeEnd":1943,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/fastapi/routing.py#L1907-L1943","documentation":"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.","triggerScenarios":"`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`.","commonSituations":"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.","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."],"exampleFix":"# before\napp.frontend(\"/\", directory=\"dist\", fallback=\"index.html\")  # dist/index.html missing\n\n# after\napp.frontend(\"/\", directory=\"dist\", fallback=\"auto\")","handlingStrategy":"validation","validationCode":"import os, stat\nfrom pathlib import Path\n\ndef assert_fallback_file(directory: str, fallback: str | None) -> None:\n    if fallback in {\"index.html\", \"404.html\"}:\n        p = Path(directory) / fallback\n        if not (p.is_file() and stat.S_ISREG(os.stat(p).st_mode)):\n            raise FileNotFoundError(f\"Fallback file missing: {p}\")\n\n# usage\nassert_fallback_file(dist, \"index.html\")\napp.frontend(\"/\", directory=dist, fallback=\"index.html\")","typeGuard":"import os\n\ndef fallback_file_present(directory: str, fallback: str | None) -> bool:\n    return fallback in {None, \"auto\"} or os.path.isfile(os.path.join(directory, fallback))","tryCatchPattern":null,"preventionTips":["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."],"tags":["frontend","static-files","fallback","configuration"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}