tiangolo/fastapi · error · HTTPException
Item not found
Error message
Item not found
What it means
Raised (status 404) by GET /items/{item_id} after the token check passes, when item_id is not a key in the in-memory fake_db dict (which only contains 'foo' and 'bar'). This is the standard 'resource does not exist' response for the tutorial's ephemeral, process-local store. Because fake_db lives only in memory, it resets every server restart and never contains items added in a previous run unless re-added.
Solutions
- Use a known id: GET /items/foo or GET /items/bar.
- If you just created the item via POST /items/, GET it in the same server process before restarting.
- Persist fake_db to a real database or file for anything beyond a tutorial.
Example fix
// before GET /items/baz // after GET /items/foo
Defensive patterns
Strategy: try-catch
Validate before calling
import httpx
KNOWN = {'foo', 'bar'}
def get_item(item_id: str):
if item_id not in KNOWN:
return None # caller decides
return httpx.get(f'http://localhost:8000/items/{item_id}', headers={'X-Token': 'coneofsilence'}) Type guard
def is_known_item(item_id: object) -> bool:
return isinstance(item_id, str) and item_id in {'foo', 'bar'} Try / catch
try:
resp = httpx.get(url, headers=headers)
resp.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
# item does not exist; handle gracefully
... Prevention
- Treat the in-memory store as ephemeral; never assume cross-restart persistence.
- GET an item in the same process that created it.
- Whitelist known ids client-side before calling.
When it happens
Trigger: Calling GET /items/baz (any id other than 'foo' or 'bar') with a valid X-Token. Also happens after a server restart if you expect an item POSTed in the previous process to still be there.
Common situations: Developer POSTs an item, restarts the dev server to pick up code changes, then GETs it and gets 404 because the in-memory dict was wiped. Or a typo in the path parameter.
Related errors
AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11).
Data as JSON: /api/errors/bfc9962b922f5972.
Report an issue: GitHub.
Appendix: source
Thrown at docs_src/app_testing/app_b_an_py310/main.py:27
"foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"},
"bar": {"id": "bar", "title": "Bar", "description": "The bartenders"},
}
app = FastAPI()
class Item(BaseModel):
id: str
title: str
description: str | None = None
@app.get("/items/{item_id}", response_model=Item)
async def read_main(item_id: str, x_token: Annotated[str, Header()]):
if x_token != fake_secret_token:
raise HTTPException(status_code=400, detail="Invalid X-Token header")
if item_id not in fake_db:
raise HTTPException(status_code=404, detail="Item not found")
return fake_db[item_id]
@app.post("/items/")
async def create_item(item: Item, x_token: Annotated[str, Header()]) -> Item:
if x_token != fake_secret_token:
raise HTTPException(status_code=400, detail="Invalid X-Token header")
if item.id in fake_db:
raise HTTPException(status_code=409, detail="Item already exists")
fake_db[item.id] = item.model_dump()
return item
View on GitHub (pinned to 3e8d1526d8)