unslothai/unsloth · error · HTTPException
ChatGPT subscriptions do not use API keys.
Error message
ChatGPT subscriptions do not use API keys.
What it means
A 400 from _validate_provider_auth_contract: the provider's auth_kind is 'chatgpt_oauth' (a ChatGPT subscription authenticated via OAuth), and the request included encrypted_api_key or set clear_api_key. ChatGPT subscription providers authenticate through OAuth tokens, not API keys, so key material in the request is a contract violation.
Source
Thrown at studio/backend/routes/providers.py:108
max_output_tokens = row.get("max_output_tokens"),
created_at = row["created_at"],
updated_at = row["updated_at"],
)
def _validate_provider_auth_contract(
info: dict,
*,
encrypted_api_key: str | None,
base_url: str | None,
models: list[str] | None,
updating: bool,
clear_api_key: bool = False,
) -> None:
if info.get("auth_kind") != "chatgpt_oauth":
return
if encrypted_api_key or clear_api_key:
raise HTTPException(status_code = 400, detail = "ChatGPT subscriptions do not use API keys.")
if base_url is not None and (not updating or base_url != info["base_url"]):
raise HTTPException(status_code = 400, detail = "ChatGPT subscription routing is fixed.")
if models is not None and (not models or not set(models).issubset(set(info["default_models"]))):
raise HTTPException(status_code = 400, detail = "Choose only curated Codex models.")
def _validate_max_output_tokens_contract(
provider_type: str,
field_was_set: bool,
value: Optional[int] = None,
) -> None:
"""Reject a non-null override on a provider type with its own documented caps.
An explicit null is allowed through everywhere: the dialog shows the field for rows
it displays as Custom but the backend stores as `openai`, and a blank field
serialises as null, so rejecting it failed every unrelated edit of those rows.
Clearing an override that cannot exist is a no-op.
"""View on GitHub (pinned to 203007d190)
Solutions
- Omit encrypted_api_key and clear_api_key entirely when auth_kind is chatgpt_oauth.
- If you meant to use an OpenAI API key, create a provider of an API-key type instead of the ChatGPT subscription type.
- In shared form code, blank out key fields for subscription-based providers before submit.
Example fix
// before
await putProvider(id, {
display_name: name,
encrypted_api_key: keyField, // always sent
});
// after
const body = { display_name: name };
if (info.auth_kind !== "chatgpt_oauth" && keyField) {
body.encrypted_api_key = keyField;
} Defensive patterns
Strategy: validation
Validate before calling
const isSubscription = (info) => info?.auth_kind === "chatgpt_oauth";
if (isSubscription(info)) { delete body.encrypted_api_key; delete body.clear_api_key; } Type guard
function isOAuthProvider(info: unknown): info is { auth_kind: "chatgpt_oauth"; default_models: string[]; base_url: string } {
return typeof info === "object" && info !== null && (info as any).auth_kind === "chatgpt_oauth";
} Prevention
- Check auth_kind from the registry before building the request body.
- Keep subscription-provider and API-key-provider forms separate.
When it happens
Trigger: POST/PUT /api/providers with provider_type whose auth_kind is chatgpt_oauth and a non-null encrypted_api_key; sending clear_api_key=true on a ChatGPT subscription row; a generic 'edit provider' form that always submits the key field.
Common situations: Frontend form reused between OpenAI-API and ChatGPT-subscription provider types; users pasting an OpenAI API key into a subscription provider; automated upsert code that includes every field regardless of auth kind.
Related errors
- Bad candidate spec fragment '{part}' (expected key=value)
- ChatGPT subscription routing is fixed.
- family {getattr(fam, 'name', fam)!r} declares no prequant_fi
- model load did not reach ready
- unknown family '{name}'
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/abeb15924021e20d.
Report an issue: GitHub.