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

  1. Ensure the user_id corresponds to an existing User row (seed the database).
  2. Confirm the postgres connection string postgresql+psycopg://postgres:postgres@localhost/db is reachable and the table exists.
  3. 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

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


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)