[macOS 26.818.41705] Thread resume signs out desktop — rotated refresh token never persisted to auth.json, fresh login invalidated in 76s
Summary
On macOS, opening/resuming an existing thread signs the app out. The desktop auth poller attempts an OAuth refresh, receives 401 refresh_token_invalidated, and the UI drops to signed-out. Logging out, having auth.json removed, and signing in fresh does not fix it — a brand-new token family is invalidated within ~76 seconds.
The distinguishing detail: the rotated refresh token is never written to auth.json. After a fresh sign-in, auth.json mtime and last_refresh never advance, so the client keeps presenting a refresh token the server has already retired.
Environment
| | |
|---|---|
| App | ChatGPT.app 26.818.41705 (CFBundleVersion 6971), bundle id com.openai.codex |
| Bundled core | codex-cli 0.149.0-alpha.4.1 (Contents/Resources/codex) |
| Workspace bundle | 26.819.11345 (node v24.19.0, python 3.12.13), arch arm64 |
| OS | macOS (Darwin 24.6.0), Apple silicon |
| Auth mode | chatgpt (ChatGPT sign-in, not API key) |
Reproduction
- Sign out from the app.
- Confirm no
ChatGPT/codexprocesses remain and~/.codex/auth.jsonis gone. - Relaunch, sign in. A new token family is written.
- Open any existing thread.
- Signed out.
Evidence
Fresh sign-in, then failure 76 seconds later:
14:39:01 sign-in; auth.json written; id_token iat 14:39:01, exp 15:39:01
14:40:17 ERROR codex_login::auth::manager
Failed to refresh token: 401 Unauthorized
{
"error": {
"message": "Your refresh token has been invalidated. Please try signing in again.",
"type": "invalid_request_error",
"code": "refresh_token_invalidated"
}
}
After that failure, ~/.codex/auth.json still holds the same refresh token written at sign-in, and last_refresh is unchanged at the sign-in timestamp. Nothing was persisted.
Every invalidation is attributed to the desktop auth poller — rpc.method="getAuthStatus" with rpc.request_id=desktop-auth:<uuid>:
caller count
desktop-auth 12
other callers 0
Several fire in the same second as thread/resume, which is the user-visible trigger.
Error attribution by client version across full log history (token_invalidated):
bundled core 0.14x 668
desktop shell 26.818 12
Onset correlates exactly with the update. The previous desktop build (26.727.51351) last logged at 20:24:51; the new build's first log is 20:25:01, and the first refresh_token_invalidated is 20:49:05 the same evening.
Notably still working
The iOS remote client (codex_chatgpt_ios_remote) has zero auth errors in the entire log history, and successfully performed a thread/resume while the desktop was failing. Its requests ride the long-lived access_token (10-day expiry) rather than driving the hourly id_token refresh. This isolates the fault to the desktop shell's auth-refresh path rather than the account, the credentials, or the backend.
Ruled out locally
- Not the workspace-settings 401 from #39189 — zero
/backend-api/accounts/*/settingsrequests and zero "Must use workspace account" messages in logs. - Not architecture — app is
arm64-only on Apple silicon, no translation involved. - Not filesystem/permissions —
auth.jsonis writable, nouchg/schgflags, 173 GB free; writes succeed at sign-in and simply never happen again. - Not the workspace dependency bundle — intact and correctly built for
arm64. - Not concurrent clients — 0 of 12 invalidations came from any client other than
desktop-auth. - Not plan-related — the first failures occurred while on a paid plan.
Expected
A 401 on refresh should not drop a session whose access_token is still valid, and a successful refresh should persist the rotated token to auth.json.
Related
- #39189 — same symptom (resume thread → sign out), different root cause, Windows
- #36525 — refresh token reuse survives logout + deleting
auth.json - #25443 — desktop stuck on refresh-token-revoked mid-session
- #15754 — "refresh token was already used"
Workaround
None on the desktop. Driving Codex from the iOS remote client continues to work.
8 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Same exact issue. i've been totally locked out of a $200 codex account for a week due to this error. ive literally tried all of the exact steps you have, deleted auth.json, reset passwords, uninstalled Codex, changed wifi.... everything i could think of. Nothing. Im about one more Troubleshoot day from just canceling.
I can reproduce this on macOS as well, with an additional potentially useful trigger: the problem started immediately after I set a ChatGPT account password in ChatGPT Settings → Account security & login → Password. This account had previously been used primarily via Sign in with Apple.
Environment:
26.818.61809chatgptObserved behavior:
/backend-api/codex/modelsreturn200 OK.getAuthStatusand logsRefreshing token.POST https://auth.openai.com/oauth/tokenreturns401 Unauthorized:The access token itself is freshly issued and unexpired when this happens.
I also ruled out stale local credentials:
~/.codex/auth.jsonaside~/.codex/auth.jsonwas createdrefresh_token_invalidatederror with the newly issued refresh token immediately afterwardSo deleting/regenerating
auth.jsondoes not fix it.The timing with setting a ChatGPT password may be relevant: changing/setting the password could reasonably invalidate existing sessions, but a fresh Codex OAuth login performed afterward also receives a refresh token that is immediately rejected, leaving Desktop in a repeated login loop.
No account IDs, email addresses, access tokens, refresh tokens, or other credentials are included here.
One additional reproduction detail that may be important: setting the ChatGPT password was not an unrelated/manual account-security change. It was prompted by the Remote Connection setup flow.
The sequence was:
refresh_token_invalidatedstate described above.~/.codex/auth.jsonand performing a fresh OAuth login does not recover Desktop; the newly issued refresh token is also rejected.So there may be a product-level reproduction path along the lines of:
social/Apple-login account → Remote Connection setup → password authentication required → set ChatGPT password → Desktop OAuth refresh-token invalidation loopThis currently leaves Desktop effectively unusable and also prevents completing the Remote Connection workflow that prompted the password setup in the first place.
Update: I found a workaround that restored Desktop for me, which may help narrow the root cause.
What worked:
This is notable because the issue had started immediately after I set a ChatGPT password for an account that had previously been used primarily via Sign in with Apple.
So the failure may involve inconsistent server/browser session state after introducing password auth to an existing social-login account, rather than a permanently broken local Desktop installation.
A possibly useful recovery path for affected users is therefore:
sign out everywhere → establish a clean web session using the original social login provider → re-authenticate DesktopThis workaround restored my Desktop session after deleting/regenerating
auth.jsonalone had not fixed the issue.Workaround that resolved this for me on 26.818.41705 (build 6971)
Still on the affected build — no rollback, no reinstall. The fix was clearing the
stale credential from both places at once. Either one alone did nothing.
What did not work: signing in from a fresh browser profile with no existing
OpenAI session. On launch the app never opened a browser at all — it silently
reused the refresh token already in
~/.codex/auth.json, so no new token wasever minted and the workaround never actually ran.
auth.jsonwas byte-identicalbefore and after (4142 b, same mtime).
What worked:
specifically (mine was timestamped identically to
auth.json's mtime, whichis how I spotted it). Logging out of all sessions is not necessary.
pgrep -fl ChatGPTto confirm — it signs out but keepsrunning, and it rewrites
auth.jsonon exit.~/.codex/auth.jsonaside. Note the app leaves the stale file in placeeven after being signed out server-side, so the app still has something to
fall back on until you remove it.
Thread resume no longer signs me out.
Evidence the rotation is now persisting, which is the actual defect in this
issue:
| | before | after |
|---|---|---|
|
auth.json| 4142 b @ 09:55 | 4168 b @ 16:40 ||
last_refresh|2026-08-24T13:55:54Z|2026-08-24T20:40:11Z|| refresh token length | 196 | 211 |
A new file with a new refresh token and a current
last_refresh— previously therotated token was never written to disk.
The important part for anyone still stuck: revoking the session server-side is
not enough on its own, because the client keeps reusing the stale local
auth.jsonwithout complaint. Both have to go.@jeremiahstjames — you mentioned deleting
auth.jsonand reinstalling withoutluck. If you did those without also revoking the specific Codex session from the
active-sessions list, that ordering may be why. Worth one more try.
Independent reproduction: Microsoft SSO + password/2FA variant on current macOS build
This report is generated by 5.6 Sol Max
I can independently reproduce the same forced sign-out loop, with a social-login variant that may help narrow the account-side trigger.
Environment
26.818.61809(build7019)0.149.0-alpha.4.326.818.41509, bundled core0.149.0-alpha.4.115.7.9(24G830), Apple Silicon M4, arm64, 32 GB RAMchatgpt; one account, no intentional account switchingTrigger
The user-visible trigger is opening an older task, switching to a new task, or opening a task that is still running. A message does not need to be sent. Task/thread navigation is followed by loss of the authenticated account and another browser sign-in prompt.
Log evidence
The macOS app logs contain 26
account_info_token_unavailablerecords across August 23–24: 17 on August 23 and 9 on August 24. These include retry bursts, so I am not claiming 26 distinct visible sign-outs.First clear failure on release
26.818.41509:Strongest sequence on current release
26.818.61809:The freshly restored authenticated account therefore became unavailable again about 20 seconds after a successful account lookup. Additional transitions occurred later on the same build at
22:52:25Z,23:15:20Z, and23:39:24Z.The bundled
codex doctor --jsoncurrently reports:There is one installed
com.openai.codexdesktop application. No active VPN or macOS system proxy was present at collection time.This extends the social-login/account-security reproduction from Apple to Microsoft SSO. A password or 2FA change can reasonably revoke older sessions once, but it does not explain a newly authenticated desktop session becoming unavailable again 20 seconds later.
I have not compared or disclosed token values, so I am not independently asserting the rotated-token persistence mechanism described in the issue body. I am confirming the same thread-navigation trigger,
auth_token_missingstate whilerefreshToken=true, explicit server-sidetoken_revokedresponse, and rapid post-login recurrence on the newest build. No email address, account ID, tokens, cookies, device serial, task/thread IDs, or raw session transcripts are included.I can confirm this issue on macOS with a very similar trigger and recovery path.
Environment:
chatgptTrigger/context:
Diagnostics:
session_index.jsonlwas also valid.thread/resumesucceeding first (errorCode=null, followed bymaybe_resume_success).refresh_token_invalidated.~/.codex/auth.json, but opening the thread still caused the same logout loop.A partial workaround did not fix it:
~/.codex/auth.jsonasideWhat finally fixed it was the full sequence:
~/.codex/auth.jsonaside.After this, thread resume stopped signing me out.
There was also a clear observable change in token rotation behavior: before opening the thread,
auth.jsonhad a freshly issued refresh token with length 196; after opening/resuming the thread successfully,auth.jsonwas rewritten,last_refreshadvanced, and the refresh token changed to length 211. This matches the successful persistence pattern reported above.So in my case the important distinction was that clearing the Codex session + local
auth.jsonwas not sufficient by itself. A complete browser logout followed by a fresh web login through the original social provider was required before recreating the Desktop OAuth state.No account identifiers, token values, hashes, email addresses, or local personal paths are included here.