{"id":"c1ba9d0c33c8a518","repo":"tiangolo/fastapi","slug":"item-not-found-there-s-only-a-plumbus-here","errorCode":null,"errorMessage":"Item not found, there's only a plumbus here","messagePattern":"Item not found, there's only a plumbus here","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"docs_src/dependencies/tutorial008c_an_py310.py","lineNumber":26,"sourceCode":"class InternalError(Exception):\n    pass\n\n\ndef get_username():\n    try:\n        yield \"Rick\"\n    except InternalError:\n        print(\"Oops, we didn't raise again, Britney 😱\")\n\n\n@app.get(\"/items/{item_id}\")\ndef get_item(item_id: str, username: Annotated[str, Depends(get_username)]):\n    if item_id == \"portal-gun\":\n        raise InternalError(\n            f\"The portal gun is too dangerous to be owned by {username}\"\n        )\n    if item_id != \"plumbus\":\n        raise HTTPException(\n            status_code=404, detail=\"Item not found, there's only a plumbus here\"\n        )\n    return item_id\n","sourceCodeStart":8,"sourceCodeEnd":30,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/docs_src/dependencies/tutorial008c_an_py310.py#L8-L30","documentation":"FastAPI returns HTTP 404 with the whimsical detail \"Item not found, there's only a plumbus here\" when `item_id` is anything other than \"plumbus\" or \"portal-gun\". The \"portal-gun\" branch raises InternalError instead (handled by the yield dependency), so this 404 only fires for genuinely unknown ids. It demonstrates custom 404 messaging combined with yield-dependency exception swallowing.","triggerScenarios":"GET /items/<anything-except-plumbus-or-portal-gun> (e.g. /items/flerb).","commonSituations":"Clients probing for resources that were never modeled; renaming the allowed id set without updating clients; tutorials copied with a different allowed-item list.","solutions":["Request GET /items/plumbus (the only valid non-portal-gun id).","If extending the API, enumerate allowed ids and document them in the OpenAPI summary.","Normalize custom 404 detail strings across endpoints for consistency.","Add a test asserting both the portal-gun InternalError path and the generic 404 path."],"exampleFix":"# before\nif item_id != \"plumbus\":\n    raise HTTPException(status_code=404, detail=\"Item not found, there's only a plumbus here\")\n\n# after\nALLOWED = {\"plumbus\"}\nif item_id not in ALLOWED:\n    raise HTTPException(status_code=404, detail=f\"Item '{item_id}' not found\")","handlingStrategy":"validation","validationCode":"ALLOWED = {\"plumbus\", \"portal-gun\"}\nif item_id not in ALLOWED:\n    raise ValueError(f\"Item '{item_id}' not supported; only {ALLOWED}\")","typeGuard":"def is_known_item(item_id: str) -> bool:\n    return item_id in {\"plumbus\", \"portal-gun\"}","tryCatchPattern":"r = client.get(f\"/items/{item_id}\")\nif r.status_code == 404:\n    # inform the user that only plumbus/portal-gun exist\n    ...","preventionTips":["Document the allowed id set in the client.","Avoid probing random ids.","Cache the supported list and refresh on schema changes."],"tags":["fastapi","http-404","not-found","dependencies","yield-dependency"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}