{"record":{"id":"7e853c48976189db","repo":"tiangolo/fastapi","slug":"hero-not-found-7e853c","errorCode":null,"errorMessage":"Hero not found","messagePattern":"Hero not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"docs_src/sql_databases/tutorial001_py310.py","lineNumber":58,"sourceCode":"    session.refresh(hero)\n    return hero\n\n\n@app.get(\"/heroes/\")\ndef read_heroes(\n    session: Session = Depends(get_session),\n    offset: int = 0,\n    limit: int = Query(default=100, le=100),\n) -> list[Hero]:\n    heroes = session.exec(select(Hero).offset(offset).limit(limit)).all()\n    return heroes\n\n\n@app.get(\"/heroes/{hero_id}\")\ndef read_hero(hero_id: int, session: Session = Depends(get_session)) -> Hero:\n    hero = session.get(Hero, hero_id)\n    if not hero:\n        raise HTTPException(status_code=404, detail=\"Hero not found\")\n    return hero\n\n\n@app.delete(\"/heroes/{hero_id}\")\ndef delete_hero(hero_id: int, session: Session = Depends(get_session)):\n    hero = session.get(Hero, hero_id)\n    if not hero:\n        raise HTTPException(status_code=404, detail=\"Hero not found\")\n    session.delete(hero)\n    session.commit()\n    return {\"ok\": True}\n","sourceCodeStart":40,"sourceCodeEnd":70,"githubUrl":"https://github.com/tiangolo/fastapi/blob/3e8d1526d83a90aaf7d6eb6dc682bf150f180b25/docs_src/sql_databases/tutorial001_py310.py#L40-L70","documentation":"Application-defined HTTPException in the read_hero GET endpoint of the tutorial. session.get(Hero, hero_id) returns None for a missing primary key, so the handler raises HTTPException(status_code=404, detail=\"Hero not found\"). FastAPI renders that as an HTTP 404 response with body {\"detail\":\"Hero not found\"}.","triggerScenarios":"A GET /heroes/{hero_id} request where no Hero row has the given primary key, for example requesting an ID that was never created, was deleted, or lives in a different database file.","commonSituations":"Requesting a hero by an ID the client guessed or cached; database.db recreated empty on startup; pointing at the wrong SQLite file; the row was deleted between a list call and a detail call.","solutions":["Verify the ID exists (e.g. via the list endpoint) before requesting the detail.","Ensure the SQLite database file is the one containing your data and was seeded.","Treat a 404 from this route as a normal 'not found' result rather than a bug.","If a missing row is common, consider returning null/204 instead of raising 404."],"exampleFix":"// before\n@app.get(\"/heroes/{hero_id}\")\ndef read_hero(hero_id: int, session: Session = Depends(get_session)) -> Hero:\n    hero = session.get(Hero, hero_id)\n    if not hero:\n        raise HTTPException(status_code=404, detail=\"Hero not found\")\n    return hero\n\n// after\n@app.get(\"/heroes/{hero_id}\", response_model=HeroPublic | None)\ndef read_hero(hero_id: int, session: Session = Depends(get_session)):\n    return session.get(Hero, hero_id)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"import httpx\ntry:\n    r = httpx.get(f\"http://localhost:8000/heroes/{hero_id}\")\n    r.raise_for_status()\n    hero = r.json()\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 404:\n        hero = None\n    else:\n        raise","preventionTips":["Fetch the list of valid IDs first and only request IDs that appear in it.","Keep the database file stable across restarts (do not let create_all wipe data).","Return Optional/None or 204 from the endpoint if absence is expected.","Log 404s separately so clients can distinguish not-found from server errors."],"tags":["sqlmodel","http-404","sql-databases","rest","fastapi"],"backgroundTag":null,"analyzedSha":"3e8d1526d83a90aaf7d6eb6dc682bf150f180b25","analyzedAt":"2026-08-11T02:34:52.986Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}