tiangolo/fastapi · error · HTTPException
Not enough permissions
Error message
Not enough permissions
What it means
Default-parameter twin of error 54: `get_current_user` raises HTTP 401 'Not enough permissions' (header `Bearer scope="..."`) when the token's scopes do not cover the route's required scopes (loop at line 132). The JWT and user are valid; only the authorization scope is missing.
Source
Thrown at docs_src/security/tutorial005_py310.py:134
detail="Could not validate credentials",
headers={"WWW-Authenticate": authenticate_value},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
scope: str = payload.get("scope", "")
token_scopes = scope.split(" ")
token_data = TokenData(scopes=token_scopes, username=username)
except (InvalidTokenError, ValidationError):
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
raise credentials_exception
for scope in security_scopes.scopes:
if scope not in token_data.scopes:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not enough permissions",
headers={"WWW-Authenticate": authenticate_value},
)
return user
async def get_current_active_user(
current_user: User = Security(get_current_user, scopes=["me"]),
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
return current_user
@app.post("/token")
async def login_for_access_token(
form_data: OAuth2PasswordRequestForm = Depends(),View on GitHub (pinned to 42a41db11f)
Solutions
- Re-request a token with the required scope(s): `scope=items` or `scope=me items`.
- Align the client's requested scopes with every route's `Security(..., scopes=...)`.
- Recheck scope strings for exact case/whitespace.
Example fix
# before # token scope=me; calling an 'items' route => 401 # after # re-login with scope='me items', then retry
Defensive patterns
Strategy: validation
Validate before calling
def has_scopes(token_scopes, required) -> bool:
return all(s in token_scopes for s in required)
# ensure 'items' (or whichever the route needs) is in token_scopes before calling Type guard
def has_required_scope(token_scopes: list[str], required: list[str]) -> bool:
return set(required).issubset(set(token_scopes)) Try / catch
try:
r = client.get('/users/me/items/', headers=auth_header(token))
r.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 401 and e.response.json().get('detail') == 'Not enough permissions':
token = request_token(scopes=['me','items'])
raise Prevention
- Request the union of scopes all target endpoints need.
- Match scope strings exactly with server config.
- On insufficient scopes, re-login for broader scopes once.
When it happens
Trigger: `GET /users/me/items/` (requires `items`) with a token whose `scope` claim lacks `items` (e.g. only `me`).
Common situations: Wrong scopes requested at /token; client assuming a scope it never obtained; required-scopes changed server-side; case/whitespace mismatch in scope strings.
Related errors
- Not enough permissions
- Incorrect username or password
- Incorrect username or password
- Not authenticated
- Inactive user
AI-assisted analysis of tiangolo/fastapi@42a41db11f (2026-08-04).
Data as JSON: /data/errors/80a392c0326bc71a.json.
Report an issue: GitHub.