{"id":"9ed5c86d5157d5e2","repo":"tiangolo/fastapi","slug":"prefix-and-path-cannot-be-both-empty-path-operati","errorCode":null,"errorMessage":"Prefix and path cannot be both empty (path operation: {name})","messagePattern":"Prefix and path cannot be both empty \\(path operation: (.+?)\\)","errorType":"exception","errorClass":"FastAPIError","httpStatus":null,"severity":"error","filePath":"fastapi/routing.py","lineNumber":3293,"sourceCode":"        )\n        if prefix:\n            assert prefix.startswith(\"/\"), \"A path prefix must start with '/'\"\n            assert not prefix.endswith(\"/\"), (\n                \"A path prefix must not end with '/', as the routes will start with '/'\"\n            )\n        else:\n            for route, route_context in _iter_routes_with_context(router.routes):\n                if route_context is None:\n                    path = getattr(route, \"path\", None)\n                    name = getattr(route, \"name\", \"unknown\")\n                elif route_context.starlette_route is not None:\n                    path = getattr(route_context.starlette_route, \"path\", None)\n                    name = getattr(route_context.starlette_route, \"name\", \"unknown\")\n                else:\n                    path = route_context.path\n                    name = route_context.name\n                if path is not None and not path:\n                    raise FastAPIError(\n                        f\"Prefix and path cannot be both empty (path operation: {name})\"\n                    )\n        include_context = _RouterIncludeContext.for_include(\n            parent_router=self,\n            included_router=router,\n            prefix=prefix,\n            tags=tags,\n            dependencies=dependencies,\n            default_response_class=default_response_class,\n            responses=responses,\n            callbacks=callbacks,\n            deprecated=deprecated,\n            include_in_schema=include_in_schema,\n            generate_unique_id_function=generate_unique_id_function,\n        )\n        self.routes.append(\n            _IncludedRouter(original_router=router, include_context=include_context)\n        )","sourceCodeStart":3275,"sourceCodeEnd":3311,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/fastapi/routing.py#L3275-L3311","documentation":"Inside `APIRouter.include_router` (routing.py:3281-3295), when no `prefix` is given FastAPI iterates the included router's routes; if any route has a `path` attribute equal to the empty string (`not path`), it raises `FastAPIError`. An empty prefix plus an empty path would resolve to an empty/invalid URL, so FastAPI refuses the include at registration time.","triggerScenarios":"Registering a path operation with an empty path — `@router.get(\"\")` — on a sub-router, then `app.include_router(router)` without a `prefix`. Also via a frontend or nested route whose effective path collapses to `\"\"` when no prefix is supplied.","commonSituations":"Defining a router whose root handler uses `\"\"` expecting the include prefix to fill it in, but forgetting the prefix; refactoring routes and dropping the leading `/`; dynamically generating `path` from a variable that can be empty.","solutions":["Give the path operation a real path, e.g. `@router.get(\"/\")` instead of `@router.get(\"\")`.","Provide a `prefix` when including: `app.include_router(router, prefix=\"/api\")`.","Validate generated path strings are non-empty before using them in a decorator."],"exampleFix":"# before\n@router.get(\"\")\ndef root(): ...\napp.include_router(router)  # no prefix -> FastAPIError\n\n# after\n@router.get(\"/\")\ndef root(): ...\napp.include_router(router)","handlingStrategy":"validation","validationCode":"def validate_route_paths(router, prefix: str = \"\") -> None:\n    if not prefix:\n        for route in router.routes:\n            path = getattr(route, \"path\", None)\n            if path is not None and not path:\n                name = getattr(route, \"name\", \"unknown\")\n                raise ValueError(\n                    f\"Route {name!r} has empty path; include with a prefix or set path='/'.\"\n                )\n\n# usage, before include:\nvalidate_route_paths(sub_router)\napp.include_router(sub_router)  # safe","typeGuard":"def all_routes_have_path_when_no_prefix(router, prefix: str) -> bool:\n    if prefix:\n        return True\n    return all(\n        getattr(r, \"path\", None) not in (\"\", None) for r in getattr(router, \"routes\", [])\n    )","tryCatchPattern":null,"preventionTips":["Always declare path operations with a leading slash, e.g. `@router.get(\"/\")`, never `\"\"`.","When including a router whose root uses `\"\"`, always pass `prefix=`.","Add a test that includes each router without a prefix to catch empty paths early."],"tags":["routing","include-router","configuration"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}