unslothai/unsloth · error · CodexAuthError

ChatGPT returned an invalid authorization response.

Error message

ChatGPT returned an invalid authorization response.

What it means

Raised as CodexAuthError when the token endpoint returns HTTP < 400 but the response body is not valid JSON (response.json() throws). This means the server (or an intermediary proxy/captive portal) returned a 200-range response with HTML or plain text instead of the expected JSON token payload, so the original exception is chained via 'from exc'.

Source

Thrown at studio/backend/core/inference/openai_codex_auth.py:285

        error_code = ""
        try:
            error = response.json().get("error")
            error_code = error.get("code", "") if isinstance(error, dict) else str(error or "")
        except Exception:
            pass
        if data.get("grant_type") == "refresh_token" and error_code in {
            "invalid_grant",
            "invalid_refresh_token",
            "refresh_token_expired",
        }:
            raise CodexReauthorizationRequired(
                "ChatGPT authorization is no longer valid. Please reconnect."
            )
        raise CodexAuthError("ChatGPT authorization failed. Please reconnect.")
    try:
        return response.json()
    except Exception as exc:
        raise CodexAuthError("ChatGPT returned an invalid authorization response.") from exc


async def _exchange_code(
    flow: OAuthFlow,
    code: str,
    *,
    verifier: str | None = None,
    redirect_uri: str | None = None,
) -> None:
    if flow.consumed:
        raise CodexAuthError("Authorization callback was already used.")
    flow.consumed = True
    try:
        body = await _token_request(
            {
                "grant_type": "authorization_code",
                "client_id": OPENAI_CODEX_CLIENT_ID,
                "code": code,

View on GitHub (pinned to 203007d190)

Solutions

  1. Check for intercepting proxies, captive portals, or SSL inspection between the host and auth.openai.com; bypass them or install the trusted CA properly.
  2. Verify the token endpoint constant resolves to the real OpenAI auth host (curl the endpoint and inspect raw body).
  3. Retry once after network conditions change; if the body is consistently HTML, fix the network/URL rather than retrying.
  4. Report transient occurrences upstream — a 2xx non-JSON body from the real endpoint is an OpenAI-side defect.

Example fix

// before
async with httpx.AsyncClient(trust_env=False) as client:  # accidentally honouring env proxy in another code path
    resp = await client.post(OPENAI_CODEX_TOKEN_URL, json=data)
return resp.json()  # raises on HTML interception page

// after
async with httpx.AsyncClient(timeout=30.0, follow_redirects=False, trust_env=False) as client:
    resp = await client.post(OPENAI_CODEX_TOKEN_URL, json=data)
if not resp.headers.get("content-type", "").startswith("application/json"):
    raise CodexAuthError("ChatGPT returned an invalid authorization response.")
return resp.json()
Defensive patterns

Strategy: retry

Validate before calling

# sanity-check network path before invoking the flow (trust_env=False means env proxies are ignored)
import httpx, socket
socket.gethostbyname("auth.openai.com")  # DNS resolves
async with httpx.AsyncClient(trust_env=False, timeout=10.0) as c:
    r = await c.get("https://auth.openai.com/")
    assert r.headers.get("content-type", "").startswith("text/html") or True

Type guard

def is_invalid_response_error(exc: BaseException) -> bool:
    return isinstance(exc, codex_auth.CodexAuthError) and "invalid" in str(exc) and "response" in str(exc)

Try / catch

try:
    bundle = await do_token_request()
except codex_auth.CodexAuthError as exc:
    if "invalid authorization response" in str(exc):
        await asyncio.sleep(2)  # possible proxy/transient corruption; one bounded retry
        bundle = await do_token_request()
    else:
        raise

Prevention

When it happens

Trigger: A transparent proxy, captive portal, or TLS-terminating middlebox intercepts the auth request and returns an HTML login/consent page with status 200; a misconfigured base URL points at a web server that returns a redirect-followed HTML page; CDN edge responses during incidents; note follow_redirects=False is set, so a 3xx would hit the >= 400 branch instead.

Common situations: Corporate networks with SSL inspection; running Studio behind a proxy that rewrites responses; OPENAI_CODEX token URL constants pointing to a wrong host; transient OpenAI outages serving error pages with 2xx status; DNS hijacking on the host.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/913787c2cdb11ee2. Report an issue: GitHub.