tiangolo/fastapi · error · HTTPException

Inactive user

Error message

Inactive user

What it means

Same as error 43 in the default-parameter style: `get_current_active_user` raises HTTP 400 'Inactive user' when `current_user.disabled` is True. The user is already authenticated; the account is simply disabled. Sample user `alice` (`disabled: True`) triggers it.

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 42a41db11f)

Solutions

  1. Use a non-disabled account (e.g. `johndoe`).
  2. Set the user's `disabled` field to `False` in the store.
  3. Show the end user a clear 'account disabled' notice; do not retry.

Example fix

# before
Authorization: Bearer alice   # disabled -> 400
# after
Authorization: Bearer johndoe  # active -> 200
Defensive patterns

Strategy: try-catch

Validate before calling

None

Type guard

def is_inactive(resp) -> bool:
    return getattr(resp, 'status_code', None) == 400 and resp.json().get('detail') == 'Inactive user'

Try / catch

try:
    me = client.get('/users/me', headers=auth_header(token))
    me.raise_for_status()
except httpx.HTTPStatusError as e:
    if e.response.status_code == 400 and e.response.json().get('detail') == 'Inactive user':
        prompt_reactivation()
    raise

Prevention

When it happens

Trigger: `GET /users/me` after authenticating as `alice`. `johndoe` (`disabled: False`) does not trigger it.

Common situations: Deactivated/suspended accounts; the `disabled` flag left True after reactivation; seeding users with the wrong flag; identical semantics to the Annotated variant.

Related errors


AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04). Data as JSON: /data/errors/df3a19588dd4e1c0.json. Report an issue: GitHub.