usestrix/strix · error · CodexAuthError

bad_response

bad_response

Error message

bad_response: token endpoint returned non-object

What it means

CodexAuthError with code `bad_response` raised when the token endpoint returns HTTP 200 but the body is not a JSON object (e.g. a JSON array, string, number, or empty content coerced to `{}`). It means the endpoint answered successfully but the OAuth contract is violated.

Source

Thrown at strix/config/codex.py:237

    detail = ""
    try:
        with requests.post(
            TOKEN_URL,
            data=payload,
            headers={"Accept": "application/json"},
            timeout=_TOKEN_TIMEOUT,
        ) as response:
            status_code = response.status_code
            body = response.content
            if status_code >= 400:
                detail = response.text[:300]
    except requests.RequestException as exc:
        raise CodexAuthError("unavailable", str(exc)) from exc
    if status_code >= 400:
        raise CodexAuthError("token_http_error", f"HTTP {status_code}: {detail}")
    data = json.loads(body or b"{}")
    if not isinstance(data, dict):
        raise CodexAuthError("bad_response", "token endpoint returned non-object")
    return data


def _record_from_token_response(
    data: dict[str, Any], refresh_fallback: str | None = None
) -> dict[str, Any]:
    access = data.get("access_token")
    # A refresh response may omit refresh_token when it isn't rotated; keep the old one.
    refresh = data.get("refresh_token") or refresh_fallback
    expires_in = data.get("expires_in")
    if not isinstance(access, str) or not access:
        raise CodexAuthError("bad_response", "token response missing access_token")
    if not isinstance(refresh, str) or not refresh:
        raise CodexAuthError("bad_response", "token response missing refresh_token")
    account_id = _account_id_from_jwt(access) or _account_id_from_jwt(
        data.get("id_token") if isinstance(data.get("id_token"), str) else ""
    )
    if not account_id:

View on GitHub (pinned to 8551339130)

Solutions

  1. Capture the raw body to identify what actually came back (add temporary logging of `body[:300]` before the parse)
  2. If behind a proxy/VPN, bypass it for auth.openai.com and retry
  3. If the endpoint contract changed, update to the latest Strix version which tracks the Codex CLI OAuth flow
  4. Re-login: `strix auth login` after fixing the network path
Defensive patterns

Strategy: retry

Try / catch

from strix.config.codex import CodexAuthError

try:
    data = exchange_code(code, verifier)
except CodexAuthError as e:
    if e.code == "bad_response" and "non-object" in str(e):
        # endpoint/proxy misbehavior — one retry on a clean path, then surface
        ...

Prevention

When it happens

Trigger: `exchange_code()` or `refresh_tokens()` receives a 200 response whose parsed JSON `isinstance(data, dict)` is False — a misbehaving gateway, HTML error page with 200 status, or API change at auth.openai.com.

Common situations: Captive portals or 'successful' proxy pages returning HTML with status 200; OpenAI changing the token endpoint shape; transparent content-inspection middleboxes mangling responses. Extremely rare in practice.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/cfe5c94286524bba. Report an issue: GitHub.