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.

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.

Appendix: 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)