tiangolo/fastapi · error · HTTPException
Not authorized
Error message
Not authorized
What it means
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.
Source
Thrown at docs_src/dependencies/tutorial014_an_py310.py:27
class User(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
app = FastAPI()
def get_session():
with Session(engine) as session:
yield session
def get_user(user_id: int, session: Annotated[Session, Depends(get_session)]):
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=403, detail="Not authorized")
session.close()
def generate_stream(query: str):
for ch in query:
yield ch
time.sleep(0.1)
@app.get("/generate", dependencies=[Depends(get_user)])
def generate(query: str):
return StreamingResponse(content=generate_stream(query))
View on GitHub (pinned to 42a41db11f)
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.
Example fix
# before
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=403, detail="Not authorized")
session.close()
# after
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=403, detail="Not authorized")
# let get_session's `with` block close the session Defensive patterns
Strategy: validation
Validate before calling
if session.get(User, user_id) is None:
raise PermissionError("Not authorized")
# only then issue the /generate request Type guard
def authorized(session, user_id: int) -> bool:
return session.get(User, user_id) is not None Try / catch
r = client.get("/generate", params={...})
if r.status_code == 403:
# surface login/permission flow
... Prevention
- 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.
When it happens
Trigger: GET /generate with a user_id that does not resolve to a User row, under the tutorial014 dependency.
Common situations: 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).
Related errors
AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04).
Data as JSON: /data/errors/58795996f2171dd9.json.
Report an issue: GitHub.