tiangolo/fastapi · error · HTTPException
Not authorized
Error message
Not authorized
What it means
HTTPException (403) raised inside the get_user dependency used by the streaming endpoint GET /generate. It looks up a User by user_id in the database via SQLModel; if no row is found, it raises 'Not authorized'. The dependency is attached via dependencies=[Depends(get_user)], so it runs before the streaming response begins. Note this returns 403 rather than the more conventional 401/404, conflating 'not found' with 'forbidden' for access-control purposes.
Solutions
- Ensure the user_id corresponds to an existing User row (seed the database).
- Confirm the postgres connection string postgresql+psycopg://postgres:postgres@localhost/db is reachable and the table exists.
- If a missing user should be 404 rather than 403, change the status code and detail accordingly.
Example fix
// before
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=403, detail="Not authorized")
// after
user = session.get(User, user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found") Defensive patterns
Strategy: validation
Validate before calling
from sqlmodel import Session, create_engine
engine = create_engine('postgresql+psycopg://postgres:postgres@localhost/db')
with Session(engine) as s:
exists = s.get(User, user_id) is not None
assert exists, f'user {user_id} missing' Type guard
def user_exists(session, user_id: int) -> bool:
return session.get(User, user_id) is not None Try / catch
resp = requests.get('http://localhost:8000/generate', params={'query': q, 'user_id': uid})
if resp.status_code == 403:
print('user not authorized/missing') Prevention
- Seed the DB with the user before calling.
- Verify connectivity to postgres and table existence.
- Consider 404 instead of 403 for missing users.
When it happens
Trigger: GET /generate?query=...&user_id=<id> where no User row with that id exists in the postgres database. The dependency requires user_id (an int query/path parameter).
Common situations: Streaming endpoints gated by ownership checks. Developers hit this when the user_id is absent (then a 422 for missing param), points at a deleted/nonexistent user, or the database is unreachable (then a different connection error). Also seen when the DB is not seeded.
Related errors
- Not authorized
- Cannot set both 'data' and 'raw_data' on the same…
- Hero not found
- Hero not found
- Hero not found
AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11).
Data as JSON: /api/errors/6aa684c6d42f364a.
Report an issue: GitHub.
Appendix: source
Thrown at docs_src/dependencies/tutorial013_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")
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 3e8d1526d8)