Skip to content

fix(codex): treat OpenAI 401/token_expired as permanent refresh failure (re-auth, not retry)#1821

Open
sacwooky wants to merge 1 commit into
decolua:masterfrom
sacwooky:fix/codex-refresh-token-expired-classification
Open

fix(codex): treat OpenAI 401/token_expired as permanent refresh failure (re-auth, not retry)#1821
sacwooky wants to merge 1 commit into
decolua:masterfrom
sacwooky:fix/codex-refresh-token-expired-classification

Conversation

@sacwooky

Copy link
Copy Markdown

Problem

When a Codex (OpenAI) OAuth refresh token is dead/invalid (expired or rotated away), OpenAI's token endpoint responds:

HTTP 401
{ "error": { "message": "Could not validate your token. Please try signing in again.",
             "type": "invalid_request_error", "code": "token_expired" } }

classifyOAuthRefreshError() only treats these as permanent: refresh_token_expired, refresh_token_reused, refresh_token_invalidated, invalid_grant. None match OpenAI's actual token_expired code, so the failure is classified transient. refreshCodexToken() then returns null instead of { error: "unrecoverable_refresh_error" }, so the caller retries the refresh (with backoff) instead of surfacing re-authentication — a retry loop that cannot succeed against a dead refresh token.

Reproduction

POST an invalid/expired refresh token to https://auth.openai.com/oauth/token and observe the real 401 token_expired payload above; running it through classifyOAuthRefreshError returns permanent: false.

Fix

  • Add token_expired (and the "could not validate your token" message) to the permanent markers.
  • Treat any 401 from the OAuth token endpoint as permanent — a 401 there means the refresh credential itself was rejected, so re-auth is the only correct outcome. 429/5xx remain transient.

Single-file change to classifyOAuthRefreshError; no behavior change for the existing markers. Verified the real OpenAI 401 token_expired payload now classifies as permanent → unrecoverable_refresh_error (re-auth).

OpenAI's token endpoint returns HTTP 401 {code:"token_expired",
type:"invalid_request_error"} for a dead/invalid (expired or rotated-away)
refresh token. The existing permanent markers (refresh_token_expired/reused/
invalidated, invalid_grant) don't match it, so refreshCodexToken classified the
failure as transient and the caller retried instead of surfacing re-auth — a
retry loop that can never succeed against a dead refresh token.

Add the token_expired marker and treat any 401 from the OAuth token endpoint as
permanent (429/5xx remain transient).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant