tiangolo/fastapi · error · AssertionError
A frontend path must start with '/'
Error message
A frontend path must start with '/'
What it means
`_normalize_frontend_path` (routing.py:1856-1857) raises `AssertionError` when the path does not start with `/`. URL path prefixes must be absolute in ASGI routing, so a relative-looking frontend path is rejected at construction time inside `APIRouter.frontend()` (routing.py:2704).
Source
Thrown at fastapi/routing.py:1857
yield RouteContext(original_route, route_context)
def _iter_routes_with_context(
routes: Sequence[BaseRoute],
) -> Iterator[tuple[BaseRoute, _EffectiveRouteContext | None]]:
for route in routes:
if isinstance(route, _IncludedRouter):
for route_context in route.effective_route_contexts():
yield route_context.original_route, route_context
else:
yield route, None
def _normalize_frontend_path(path: str) -> str:
if not path:
raise AssertionError("A frontend path cannot be empty")
if not path.startswith("/"):
raise AssertionError("A frontend path must start with '/'")
if path != "/":
path = path.rstrip("/")
return path
def _join_frontend_paths(prefix: str, path: str) -> str:
if not prefix:
return path
if path == "/":
return prefix
return prefix + path
def _frontend_path_specificity(path: str) -> int:
if path == "/":
return 0
return len(path)
View on GitHub (pinned to 42a41db11f)
Solutions
- Prefix the path with `/` before calling `.frontend()` (e.g. `f"/{name.lstrip('/')}"`).
- Use `"/"` for root or `"/<segment>"` for a sub-mount.
- Normalize config-driven paths in one place so the value always starts with `/`.
Example fix
# before
app.frontend("app", directory="dist")
# after
app.frontend("/app", directory="dist") Defensive patterns
Strategy: validation
Validate before calling
def normalize_frontend_path(path: str) -> str:
if not path:
raise ValueError("frontend path cannot be empty")
if not path.startswith("/"):
path = "/" + path.lstrip("/")
return path
# usage
app.frontend(normalize_frontend_path(raw_path), directory="dist") Type guard
def is_absolute_frontend_path(path: object) -> bool:
return isinstance(path, str) and path.startswith("/") Prevention
- Never `.strip()` or `.lstrip("/")` a path right before passing it to `.frontend()`.
- Centralize path construction so segments always carry their leading slash.
- Add a startup assertion over all configured mounts.
When it happens
Trigger: Calling `app.frontend("app", directory="dist")` (missing leading slash) or any `.frontend(path)` where path is e.g. `"static"`, `"spa"`, or `"/"` stripped by mistake.
Common situations: Stripping a leading `/` via `path.lstrip("/")` or `path.strip()` before passing it; building the path from a route name without normalizing; reading a prefix from config stored without the slash.
Related errors
- A frontend path cannot be empty
- Frontend directory '{directory}' does not exist. Resolved ab
- Frontend fallback file '{fallback}' does not exist in direct
- 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/a554f22b66fa841c.json.
Report an issue: GitHub.