ruvnet/RuView · error · HTTPException
Permission '{permission}' required
Error message
Permission '{permission}' required What it means
require_permission(permission) is a dependency factory; the closure it returns raises 403 with the interpolated message when the user is not an admin and the permission string is not in the user's permissions list. Admin users bypass the check entirely.
Source
Thrown at archive/v1/src/api/dependencies.py:162
# Permission dependencies
def require_permission(permission: str):
"""Dependency factory for permission checking."""
async def check_permission(
current_user: Dict[str, Any] = Depends(get_current_active_user)
) -> Dict[str, Any]:
"""Check if user has required permission."""
user_permissions = current_user.get("permissions", [])
# Admin users have all permissions
if current_user.get("is_admin", False):
return current_user
# Check specific permission
if permission not in user_permissions:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"Permission '{permission}' required"
)
return current_user
return check_permission
# Zone access dependencies
async def validate_zone_access(
zone_id: str,
current_user: Optional[Dict[str, Any]] = Depends(get_current_user)
) -> str:
"""Validate user access to a specific zone."""
domain_config = get_domain_config()
# Check if zone existsView on GitHub (pinned to 4685618388)
Solutions
- Inspect the user's permissions (decode the token or query the account) and obtain the missing permission
- Align permission strings between the token issuer/database and the require_permission call site
- Re-login or re-issue the token so updated permissions propagate
- If the caller should bypass the check, use an admin account
Defensive patterns
Strategy: validation
Validate before calling
# Verify the required permission locally before the call
REQUIRED = 'zones:write'
claims = jwt.decode(token, options={'verify_signature': False})
perms = set(claims.get('permissions', []))
if not claims.get('is_admin', False) and REQUIRED not in perms:
raise PermissionError(f'Missing permission: {REQUIRED}')
client.post('/api/zones', headers={'Authorization': f'Bearer {token}'}, json=payload) Try / catch
try:
r = client.post('/api/zones', headers=auth, json=payload)
r.raise_for_status()
except httpx.HTTPStatusError as e:
if e.response.status_code == 403 and 'Permission' in (e.response.json().get('detail') or ''):
request_permission(e.response.json()['detail']) # surface which permission is missing
raise Prevention
- Define permission strings as constants shared by issuer and API to prevent drift
- Re-issue tokens after any permission-model change
- Surface the missing permission name from the 403 detail in the UI
When it happens
Trigger: Calling an endpoint whose require_permission('...') string does not match any entry in the user's permissions claim; permission renamed in code while tokens/database still carry the old name; user with an empty permissions list hitting a gated endpoint.
Common situations: Permission model refactors without re-issuing tokens; feature-gated endpoints; mismatched permission naming between the identity source and the API code.
Related errors
- Inactive user
- Admin privileges required
- Access denied to zone '{zone_id}'
- Access denied to router '{router_id}'
- Not enough permissions. Required scope: {scope}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/53f05488ba94291a.
Report an issue: GitHub.