tiangolo/fastapi · error · HTTPException

Inactive user

Error message

Inactive user

What it means

Same disabled-account gate as error 40, but in the legacy dependency-injection syntax (current_user: User = Depends(...) instead of Annotated[User, Depends(...)]). After get_current_user resolves the token to a valid user, line 68 rejects disabled users with HTTP 400 'Inactive user'. Functionally identical to error 40; only the DI style differs.

Solutions

  1. Use an active user (disabled=False), e.g. 'johndoe'.
  2. Flip disabled to False in fake_users_db for the account and re-send the request.
  3. Migrate the raise to 403 Forbidden for disabled-but-authenticated users.

Example fix

// before
if current_user.disabled:
    raise HTTPException(status_code=400, detail="Inactive user")

// after
if current_user.disabled:
    raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Inactive user")
Defensive patterns

Strategy: try-catch

Validate before calling

DISABLED_USERS = {"alice"}
def looks_active(token_or_username: str) -> bool:
    return token_or_username not in DISABLED_USERS

Type guard

from typing import TypeGuard
def is_active_user(u: dict) -> TypeGuard[dict]:
    return not u.get("disabled", False)

Try / catch

import httpx
try:
    r = httpx.get("/users/me", headers={"Authorization": f"Bearer {token}"})
    r.raise_for_status()
except httpx.HTTPStatusError as e:
    if e.response.status_code == 400 and e.response.json().get("detail") == "Inactive user":
        prompt_reactivation()

Prevention

When it happens

Trigger: GET /users/me (or any route depending on get_current_active_user) with a token resolving to a user whose disabled flag is True — e.g. token 'alice' because fake_decode_token uses the token as the username key.

Common situations: Using the seeded disabled 'alice' fixture; admin-suspended accounts; users modelled as disabled until email verification.

Related errors


AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11). Data as JSON: /api/errors/df3a19588dd4e1c0. Report an issue: GitHub.

Appendix: source

Thrown at docs_src/security/tutorial003_py310.py:69

    # Check the next version
    user = get_user(fake_users_db, token)
    return user


async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_decode_token(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Not authenticated",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return user


async def get_current_active_user(current_user: User = Depends(get_current_user)):
    if current_user.disabled:
        raise HTTPException(status_code=400, detail="Inactive user")
    return current_user


@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user_dict = fake_users_db.get(form_data.username)
    if not user_dict:
        raise HTTPException(status_code=400, detail="Incorrect username or password")
    user = UserInDB(**user_dict)
    hashed_password = fake_hash_password(form_data.password)
    if not hashed_password == user.hashed_password:
        raise HTTPException(status_code=400, detail="Incorrect username or password")

    return {"access_token": user.username, "token_type": "bearer"}


@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_active_user)):

View on GitHub (pinned to 3e8d1526d8)