{"record":{"id":"89e90dcc5e28695b","repo":"tiangolo/fastapi","slug":"a-frontend-path-cannot-be-empty","errorCode":null,"errorMessage":"A frontend path cannot be empty","messagePattern":"A frontend path cannot be empty","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"fastapi/routing.py","lineNumber":1855,"sourceCode":"                yield RouteContext(original_route)\n            else:\n                yield RouteContext(original_route, route_context)\n\n\ndef _iter_routes_with_context(\n    routes: Sequence[BaseRoute],\n) -> Iterator[tuple[BaseRoute, _EffectiveRouteContext | None]]:\n    for route in routes:\n        if isinstance(route, _IncludedRouter):\n            for route_context in route.effective_route_contexts():\n                yield route_context.original_route, route_context\n        else:\n            yield route, None\n\n\ndef _normalize_frontend_path(path: str) -> str:\n    if not path:\n        raise AssertionError(\"A frontend path cannot be empty\")\n    if not path.startswith(\"/\"):\n        raise AssertionError(\"A frontend path must start with '/'\")\n    if path != \"/\":\n        path = path.rstrip(\"/\")\n    return path\n\n\ndef _join_frontend_paths(prefix: str, path: str) -> str:\n    if not prefix:\n        return path\n    if path == \"/\":\n        return prefix\n    return prefix + path\n\n\ndef _frontend_path_specificity(path: str) -> int:\n    if path == \"/\":\n        return 0","sourceCodeStart":1837,"sourceCodeEnd":1873,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/fastapi/routing.py#L1837-L1873","documentation":"Raised by `_normalize_frontend_path` (fastapi/routing.py:1855) when the `path` argument passed to `router.frontend(path, ...)` (or an internal join) is an empty string. FastAPI needs a non-empty path segment to register the frontend static-file routes, so an empty value is treated as a programmer error and fails fast with an AssertionError at app/route setup time.","triggerScenarios":"Calling `router.frontend('', directory='dist')` or `app.frontend('', directory='dist')`. Also triggered if a router with an empty `prefix` calls `frontend` such that `_join_frontend_paths` yields an empty combined path.","commonSituations":"Building the path from a variable that resolved to an empty string (e.g. `os.environ.get('FRONTEND_BASE')` returning ''). Passing `path.strip()` after trimming whitespace off a misconfigured value. Copy-pasting a `frontend(...)` call and forgetting to fill in the first positional argument.","solutions":["Pass a path that begins with '/', typically '/': `router.frontend('/', directory='dist')`.","If the path comes from configuration, default it: `frontend(os.environ.get('FRONTEND_BASE') or '/', directory='dist')`.","Add an assertion or validation of the config value at startup before calling `frontend`."],"exampleFix":"// before\nrouter.frontend('', directory='dist')\n// after\nrouter.frontend('/', directory='dist')","handlingStrategy":"validation","validationCode":"from fastapi import APIRouter\n\ndef safe_frontend(router: APIRouter, path: str | None, directory: str) -> None:\n    if not path:\n        raise ValueError('frontend path must not be empty')\n    router.frontend(path, directory=directory)","typeGuard":"def is_valid_frontend_path(path: object) -> bool:\n    return isinstance(path, str) and path != ''","tryCatchPattern":null,"preventionTips":["Default config-driven paths to '/' instead of None/empty.","Validate path strings at startup before calling router.frontend.","Treat frontend paths as URL paths (must start with '/'), not filesystem paths."],"tags":["fastapi","frontend-routing","configuration","assertion"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}