{"id":"58795996f2171dd9","repo":"tiangolo/fastapi","slug":"not-authorized-587959","errorCode":null,"errorMessage":"Not authorized","messagePattern":"Not authorized","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"docs_src/dependencies/tutorial014_an_py310.py","lineNumber":27,"sourceCode":"\n\nclass User(SQLModel, table=True):\n    id: int | None = Field(default=None, primary_key=True)\n    name: str\n\n\napp = FastAPI()\n\n\ndef get_session():\n    with Session(engine) as session:\n        yield session\n\n\ndef get_user(user_id: int, session: Annotated[Session, Depends(get_session)]):\n    user = session.get(User, user_id)\n    if not user:\n        raise HTTPException(status_code=403, detail=\"Not authorized\")\n    session.close()\n\n\ndef generate_stream(query: str):\n    for ch in query:\n        yield ch\n        time.sleep(0.1)\n\n\n@app.get(\"/generate\", dependencies=[Depends(get_user)])\ndef generate(query: str):\n    return StreamingResponse(content=generate_stream(query))\n","sourceCodeStart":9,"sourceCodeEnd":40,"githubUrl":"https://github.com/tiangolo/fastapi/blob/42a41db11f6882807ac3c057b942178d53b97438/docs_src/dependencies/tutorial014_an_py310.py#L9-L40","documentation":"Same HTTP 403 \"Not authorized\" as error 32, but in tutorial014 the `get_user` dependency additionally calls `session.close()` after the not-found check. The 403 is raised before session.close(), so the response is identical to 00813; the close is there to demonstrate explicit cleanup within a dependency that uses an externally-managed session.","triggerScenarios":"GET /generate with a user_id that does not resolve to a User row, under the tutorial014 dependency.","commonSituations":"Same as error 32; specifically when the dependency manually closes the session before the StreamingResponse consumes it (which can cause issues if the stream needs the session).","solutions":["Pass an existing user_id.","Ensure the User table is created and seeded.","Do not close the session before the StreamingResponse if later code needs it; let the session dependency manage its lifecycle.","Prefer 404 if existence-leak is acceptable."],"exampleFix":"# before\nuser = session.get(User, user_id)\nif not user:\n    raise HTTPException(status_code=403, detail=\"Not authorized\")\nsession.close()\n\n# after\nuser = session.get(User, user_id)\nif not user:\n    raise HTTPException(status_code=403, detail=\"Not authorized\")\n# let get_session's `with` block close the session","handlingStrategy":"validation","validationCode":"if session.get(User, user_id) is None:\n    raise PermissionError(\"Not authorized\")\n# only then issue the /generate request","typeGuard":"def authorized(session, user_id: int) -> bool:\n    return session.get(User, user_id) is not None","tryCatchPattern":"r = client.get(\"/generate\", params={...})\nif r.status_code == 403:\n    # surface login/permission flow\n    ...","preventionTips":["Let the session dependency manage its lifecycle; avoid closing in get_user.","Seed test users for integration tests.","Distinguish 403 (auth) from streaming errors that occur mid-stream."],"tags":["fastapi","authorization","sqlmodel","http-403","dependencies","session-management"],"analyzedSha":"42a41db11f6882807ac3c057b942178d53b97438","analyzedAt":"2026-08-04T19:23:32.007Z","schemaVersion":2}