{"id":"7d649d4cdf11b026","repo":"tiangolo/fastapi","slug":"username","errorCode":null,"errorMessage":"{username}","messagePattern":"\\{username\\}","errorType":"exception","errorClass":"OwnerError","httpStatus":400,"severity":"error","filePath":"docs_src/dependencies/tutorial008b_an_py310.py","lineNumber":31,"sourceCode":"\nclass OwnerError(Exception):\n    pass\n\n\ndef get_username():\n    try:\n        yield \"Rick\"\n    except OwnerError as e:\n        raise HTTPException(status_code=400, detail=f\"Owner error: {e}\")\n\n\n@app.get(\"/items/{item_id}\")\ndef get_item(item_id: str, username: Annotated[str, Depends(get_username)]):\n    if item_id not in data:\n        raise HTTPException(status_code=404, detail=\"Item not found\")\n    item = data[item_id]\n    if item[\"owner\"] != username:\n        raise OwnerError(username)\n    return item\n","sourceCodeStart":13,"sourceCodeEnd":33,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/docs_src/dependencies/tutorial008b_an_py310.py#L13-L33","documentation":"A custom OwnerError is raised inside the path operation when an item exists in the in-memory `data` store but its `owner` field does not match the username yielded by the `get_username` dependency (hard-coded to \"Rick\"). Because `get_username` is a yield-based dependency, FastAPI routes the exception back into the dependency's `except OwnerError` block, which converts it into HTTP 400 with detail \"Owner error: <username>\". The `{username}` payload is the identity that was denied access. This example demonstrates FastAPI's yield-dependency cleanup-and-exception-handling pattern.","triggerScenarios":"GET /items/{item_id} for item_id \"plumbus\" (owner=\"Morty\") with the dependency-injected username=\"Rick\"; the owner mismatch trips `if item[\"owner\"] != username: raise OwnerError(username)`.","commonSituations":"Authorization/ownership checks implemented as exceptions inside handlers wired to yield-based session/user dependencies; replacing the toy `get_username` with a real auth provider whose returned identity differs from the resource's stored owner; changing the `data` dict's owner values during refactoring without updating the dependency.","solutions":["Pass credentials that match the item's owner, or request an item owned by the yielded user (e.g. \"portal-gun\" which is owned by Rick).","If you own the code, change the owner check to return HTTP 403 with a descriptive detail instead of a bare OwnerError so clients get a stable status code.","Make get_username resolve the real authenticated principal from a header/token rather than the hardcoded \"Rick\" so ownership matches expectations.","Add an integration test asserting which item_ids each user may read."],"exampleFix":"# before\ndef get_item(item_id: str, username: Annotated[str, Depends(get_username)]):\n    if item[\"owner\"] != username:\n        raise OwnerError(username)\n\n# after\nif item[\"owner\"] != username:\n    raise HTTPException(status_code=403, detail=f\"{username} is not the owner of {item_id}\")","handlingStrategy":"validation","validationCode":"# Before calling /items/{item_id}, ensure your principal matches the item owner\nKNOWN_OWNERS = {\"plumbus\": \"Morty\", \"portal-gun\": \"Rick\"}\nUSERNAME = \"Rick\"\ndef can_read(item_id: str) -> bool:\n    return KNOWN_OWNERS.get(item_id) == USERNAME\n# only call when can_read(item_id) is True","typeGuard":"def is_owned_by(item_id: str, owner: str, store: dict[str, dict]) -> bool:\n    item = store.get(item_id)\n    return bool(item) and item.get(\"owner\") == owner","tryCatchPattern":"import httpx\nwith httpx.Client(base_url=\"http://localhost:8000\") as c:\n    r = c.get(f\"/items/{item_id}\")\n    if r.status_code == 400 and r.json().get(\"detail\", \"\").startswith(\"Owner error:\"):\n        # ownership denied; pick a different item or escalate permissions\n        ...","preventionTips":["Centralize ownership rules in a service the client consults before issuing requests.","Document, per resource, which principal may access it.","Treat 400 'Owner error' as authorization denial and stop retrying the same id."],"tags":["fastapi","dependencies","authorization","yield-dependency","http-400"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}