odysseus-dev/odysseus · error · HTTPException
API token is not scoped for chat
Error message
API token is not scoped for chat
What it means
Authorization guard in api_models: the request was authenticated with an API token whose scopes do not include 'chat'. Token-scoped callers may only list models if their token grants the chat scope; the 403 prevents tokens from enumerating the model list beyond their granted scope.
Solutions
- Use an API token that includes the chat scope.
- Create a new token with chat scope in the token management UI.
Defensive patterns
Strategy: validation
When it happens
Trigger: Triggered when the corresponding server-side validation or runtime check at the recorded location rejects the request or operation and returns this error message to the caller.
Common situations: See trigger scenarios.
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/e299357634ad849d.
Report an issue: GitHub.
Appendix: source
Thrown at routes/model_routes.py:1628
"category": category,
"endpoint_kind": kind,
"model_type": ep_model_type,
"offline": True,
})
return {"hosts": [], "items": items}
@router.get("/models")
def api_models(request: Request, refresh: bool = False, background: bool = False):
"""Get available models — per-user (caller sees only their endpoints +
legacy/shared null-owner rows). Cached per-user for 30s."""
# Require auth; "" is the unconfigured single-user mode, treated as
# "see everything" by _fetch_models.
try:
if getattr(request.state, "api_token", False):
scopes = set(getattr(request.state, "api_token_scopes", []) or [])
if "chat" not in scopes:
raise HTTPException(403, "API token is not scoped for chat")
if not getattr(request.state, "api_token_owner", None):
raise HTTPException(403, "API token has no owner")
owner = effective_user(request) or ""
# Reject anonymous in configured deployments — no leaking the model
# list to unauthenticated callers.
auth_mgr = getattr(request.app.state, "auth_manager", None)
if not owner and not _auth_disabled() and auth_mgr is not None and getattr(auth_mgr, "is_configured", False):
raise HTTPException(401, "Not authenticated")
except HTTPException:
raise
except Exception as e:
logger.error("Auth gate error in GET /api/models, failing closed: %s", e)
raise HTTPException(status_code=500, detail="Internal error")
# Admins see every endpoint (they manage the global pool); regular
# users get the owner-scoped view.
_is_admin = False
try:View on GitHub (pinned to f9235ebbf1)