unslothai/unsloth · error · HTTPException
Choose only curated Codex models.
Error message
Choose only curated Codex models.
What it means
A 400 from _validate_provider_auth_contract: for a chatgpt_oauth provider, the models list was supplied but was empty or contained at least one model outside the provider's curated default_models set. ChatGPT subscriptions expose only a fixed, curated Codex model list; arbitrary model names are rejected.
Source
Thrown at studio/backend/routes/providers.py:112
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.
"""
if field_was_set and value is not None and provider_type != "custom":
raise HTTPException(
status_code = 400,
detail = "Max Tokens limit can only be overridden for generic Custom providers.",View on GitHub (pinned to 203007d190)
Solutions
- Send models as a subset of the provider's default_models (visible via GET /api/providers/registry or the provider row).
- Send null/omit the field to keep the defaults instead of sending an empty array.
- If you need a non-curated model, use an API-key-based provider type.
Example fix
// before
await putProvider(id, { models: [] }); // -> 400
// after
await putProvider(id, { models: curatedModels.filter(m => selected.has(m)) });
// or omit `models` entirely to keep defaults Defensive patterns
Strategy: validation
Validate before calling
const allowed = new Set(info.default_models ?? []); const models = requestedModels.filter(m => allowed.has(m)); if (models.length === 0) delete body.models; // never send [] to a subscription provider else body.models = models;
Prevention
- Build the model picker options from the provider's default_models.
- Distinguish 'no selection' (omit field) from 'empty list' (never send).
When it happens
Trigger: PUT with models: [] (explicit empty list); models containing a model name not in info['default_models'] (e.g. an OpenAI API model id); syncing model lists from an OpenAI-API provider onto a subscription provider.
Common situations: Copy-pasting model names between provider types; UI 'select models' control submitting an empty selection instead of null; hard-coded model lists in client code.
Related errors
- {rejection_message}
- Invalid model snapshot repository ID.
- Only trained or exported Unsloth models can be deleted
- ChatGPT subscriptions do not use API keys.
- ChatGPT subscription routing is fixed.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/ba98c5c827c4f01d.
Report an issue: GitHub.