If you call app.get('/') without the @ decorator, FastAPI registers nothing. That means no route exists, so every request returns 404. This is the most common mistake:
# ❌ WRONG:
app.get('/')
def root():
return {'msg': 'hello'}
# ✅ CORRECT:
@app.get('/')
def root():
return {'msg': 'hello'}
Often, your script will include routers or static mounts, but if the decorators aren’t applied properly, nothing gets registered. Here's a robust minimal example that you can copy into main.py and test:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/")
def hello():
return {"hello": "world"}
@app.get("/abc")
def abc():
return {"hello": "abc"}
Run it with:
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Navigate to GET /, /abc, or /static/…—they should all work. If GET / still returns 404, re‑check your decorators.
If you're including an APIRouter:
from fastapi import FastAPI, APIRouter
router = APIRouter(prefix="/items")
@router.get("/")
async def list_items():
return ["a", "b"]
app = FastAPI()
app.include_router(router)
Your route is reachable at /items/, not /. So GET / → 404, GET /items/ → 200 with ["a","b"]. This is another source of “missing” routes.
root_pathIf you're hosting behind a proxy (Nginx, Traefik, API Gateway, etc.) that strips or adds leading path segments, FastAPI’s OpenAPI UI /docs or even paths can break. Use the root_path feature:
Via code:
app = FastAPI(root_path="/myapp")
Via Uvicorn CLI:
uvicorn main:app --root-path "/myapp"
This ensures both routing and docs work with the prefixed path.
Check you’re in the correct working directory (project root).
Temporarily hardcode a simple root route:
@app.get("/")
def debug_root():
return {"ok": True}
Print the registered routes to verify:
for r in app.routes:
print(r.path, r.methods)
Then run your service and inspect output to know exactly what endpoints exist.