usestrix/strix · error · CodexAuthError

no_account_id

no_account_id

Error message

no_account_id: could not read chatgpt_account_id from token

What it means

CodexAuthError with code `no_account_id` raised when Strix cannot extract `chatgpt_account_id` from either the access token JWT or the id_token JWT. Strix needs the account ID to route inference to the right ChatGPT backend account, so it refuses to save an unusable credential.

Source

Thrown at strix/config/codex.py:256

    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:
        raise CodexAuthError("no_account_id", "could not read chatgpt_account_id from token")
    ttl = expires_in if isinstance(expires_in, int | float) else 3600
    return {
        "type": "oauth",
        "provider": PROVIDER,
        "access": access,
        "refresh": refresh,
        "account_id": account_id,
        "expires_at": time.time() + ttl,
    }


def exchange_code(code: str, verifier: str) -> dict[str, Any]:
    data = _post_form(
        {
            "grant_type": "authorization_code",
            "client_id": CLIENT_ID,
            "code": code,
            "code_verifier": verifier,

View on GitHub (pinned to 8551339130)

Solutions

  1. Update Strix to the latest release — claim-parsing fixes track OpenAI changes quickly
  2. Re-login (`strix auth logout && strix auth login`) to obtain freshly-shaped tokens
  3. Decode your token (jwt.io or `base64 -d` on the payload segment) and check the `https://api.openai.com/auth` claim exists; if absent, the account/token type is unsupported for Codex auth — use an API key provider instead
  4. Report upstream with the decoded claim shape (never paste the token itself)
Defensive patterns

Strategy: try-catch

Type guard

def codex_record_usable(record: dict) -> bool:
    return bool(
        isinstance(record, dict)
        and record.get("type") == "oauth"
        and record.get("access")
        and record.get("refresh")
        and record.get("account_id")
    )

Try / catch

from strix.config.codex import CodexAuthError

try:
    access, account = get_valid_token()
except CodexAuthError as e:
    if e.code == "no_account_id":
        # token shape unsupported — re-login; if persistent, switch to API-key provider
        ...

Prevention

When it happens

Trigger: During login or refresh: `_account_id_from_jwt(access)` and `_account_id_from_jwt(id_token)` both return None — the JWT payload's `https://api.openai.com/auth` claim is absent or malformed (e.g. opaque/non-JWT access tokens, or claim shape changed).

Common situations: OpenAI changing token claims for the Codex backend; account types (e.g. free-tier or enterprise) whose tokens lack the claim; a Strix version that predates a claim-shape change by OpenAI.

Related errors


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