unslothai/unsloth · error · CodexReauthorizationRequired

ChatGPT authorization is no longer valid. Please reconnect.

Error message

ChatGPT authorization is no longer valid. Please reconnect.

What it means

Raised as CodexReauthorizationRequired (a subclass of CodexAuthError) when a refresh_token grant to OpenAI's OAuth token endpoint returns HTTP >= 400 with an error code of invalid_grant, invalid_refresh_token, or refresh_token_expired. It means the stored refresh token can no longer mint new access tokens, so the ChatGPT connection must be re-established by the user. Callers (e.g. openai_codex_client.py) catch CodexReauthorizationRequired specifically and mark the provider bundle with reauthorization_required=True so subsequent calls fail fast with the same message.

Source

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

        async with httpx.AsyncClient(
            timeout = 30.0, follow_redirects = False, trust_env = False
        ) as client:
            response = await client.post(OPENAI_CODEX_TOKEN_URL, data = data)
    except httpx.HTTPError as exc:
        raise CodexAuthError("Could not reach ChatGPT authentication.") from exc
    if response.status_code >= 400:
        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.")

View on GitHub (pinned to 203007d190)

Solutions

  1. Catch CodexReauthorizationRequired in the caller and surface a 'reconnect ChatGPT' action to the user instead of retrying — the token is dead.
  2. Delete or disconnect the stored OAuth bundle for the provider_id (the disconnect/delete path clears the bundle) and start a new browser or device flow.
  3. If it recurs immediately after reconnect, check that multiple Studio workers share the installation DB and are not racing token refresh (the provider_oauth_write_guard exists for this).
  4. Verify the system clock is correct; large skew can cause the client to refresh too late against an already-rotated token.

Example fix

// before
try:
    token, account = await resolve_access(provider_id)
except CodexAuthError as exc:
    log.warning("auth failed, retrying")
    raise

// after
try:
    token, account = await resolve_access(provider_id)
except CodexReauthorizationRequired:
    # refresh token revoked/expired - user must reconnect, do not retry
    await mark_reauthorization_required(provider_id)
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

from studio.backend.core.inference import openai_codex_auth as codex_auth

status = codex_auth.get_oauth_status(provider_id)
# status == 'reauthorization_required' predicts this error before any call
if status == "reauthorization_required":
    prompt_reconnect()

Type guard

def is_reauthorization_required(exc: BaseException) -> bool:
    """True when the refresh token is dead and the user must reconnect."""
    return isinstance(exc, codex_auth.CodexReauthorizationRequired)

Try / catch

try:
    token, account = await resolve_access(provider_id)
except CodexReauthorizationRequired:
    # terminal: surface reconnect UX, never retry
    await show_reconnect_prompt(provider_id)
except CodexAuthError as exc:
    # other auth failures: log and handle separately
    log.warning("codex auth failed: %s", exc)

Prevention

When it happens

Trigger: A call to resolve_access() where the cached access token has expired (bundle['expires_at'] <= time.time() + _REFRESH_SKEW_SECONDS), causing _token_request with grant_type='refresh_token' to receive a 400 response whose JSON error code is 'invalid_grant', 'invalid_refresh_token', or 'refresh_token_expired'. Also produced on force_refresh=True when the saved refresh token was revoked or expired server-side.

Common situations: The user revoked the app in their OpenAI/ChatGPT account settings; the refresh token exceeded OpenAI's rotation window; the installation DB was restored from another machine with stale credentials; the account password changed or the session was invalidated; multiple Studio workers raced a refresh and one consumed the rotated token.

Related errors


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