Windows desktop: startup hangs on blank window after auth bootstrap 401 (no retry, no error surfaced)

Open 💬 3 comments Opened Jul 1, 2026 by tdmackey
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Codex Desktop (Windows) — startup hangs on a blank window after auth bootstrap 401

Reporter timezone: America (UTC‑7). Log timestamps are UTC (local = UTC − 7h).
Report generated: 2026‑06‑30 18:02 local (2026‑07‑01 01:02 UTC)

---

1. Summary

Codex Desktop launches, spawns the local app‑server (codex.exe) successfully, opens
its main window, fires ready-to-show, and requests the React root render — but the
renderer never paints. The window sits completely blank (dark) indefinitely.

Root cause in the logs: the very first authenticated call to the ChatGPT backend
(POST /wham/statsig/bootstrap) returns 401 Unauthorized. The client attempts a
token refresh, the refresh yields no token (auth_token_missing /
tokenExpiryState=missing), and from that point every request goes out with
hadToken=false → repeated 401s. The app then never retries auth — for the next
~6.5 minutes the only log activity is bundled_plugins_reconcile_skipped_features_unavailable
reason=focus
. The UI is wedged with "features unavailable" and no recovery path.

Two product bugs are visible here:

  1. No self‑healing / no user‑visible error. A failed statsig/auth bootstrap at

startup leaves a permanently blank window with no spinner, no error, no
"sign in again" prompt, and no retry. The app should surface the auth failure and/or
retry, rather than render nothing forever.

  1. hasToken=false despite a valid, non‑expired auth.json on disk. At the moment

of failure the on‑disk access_token was still valid (exp 2026‑07‑02, ~27h in the
future) and a refresh_token was present, yet the app‑server reported
hasToken=false nullReason=auth_token_missing. The failed refresh appears to have
dropped the in‑memory token instead of falling back to the still‑valid cached access
token.

Workaround that fixed it: fully kill all Codex processes (8 were alive), then
relaunch. Simply relaunching from the icon re‑focused the still‑running wedged instance
and did nothing. Reset-AppxPackage also did nothing (it clears the MSIX container but
not ~/.codex, and does not terminate the running Electron processes).

---

2. Environment

| Item | Value |
|---|---|
| OS | Windows 11 Pro, Build 26200 (10.0.26200.0) |
| Desktop app (installed MSIX) | OpenAI.Codex 26.623.9142.0 x64, SignatureKind=Store, Status=Ok |
| Desktop app (config BROWSER_USE_CODEX_APP_VERSION) | 26.623.61825 (note: mismatch vs installed 26.623.9142.0 — possible update in between) |
| App‑server / CLI | codex-cli 0.142.4 (log: Current reported app-server version: currentVersion=0.142.4) |
| Package family | OpenAI.Codex_2p2nqsd0c76g0 |
| AUMID | OpenAI.Codex_2p2nqsd0c76g0!App |
| CODEX_HOME | C:\Users\<user>\.codex |
| buildFlavor | prod, packaged=true |

---

3. Timeline of the wedged launch (all UTC)

| Time (UTC) | Event |
|---|---|
| 00:52:26.984 | Launching app |
| 00:52:27.336 | app‑server connection starting (hostId=local, stdio) |
| 00:52:29.564 | 2 saved remote connections loaded; window‑context selected remote‑ssh transport remote-ssh-codex-managed:mustafar.home.arpa (autoConnectConnectionCount=1) |
| 00:52:29.945 | local codex.exe spawned (pid 29540); transport start success |
| 00:52:30.069 | Codex CLI initialized (handshake 124 ms, outcome=success) |
| 00:52:30.205 | window main frame finished load (startupElapsedMs=95) |
| 00:52:30.234 | window ready-to-show (startupElapsedMs=125) |
| 00:52:32.517 | React root render requested (renderer visible+focused) |
| 00:52:32.825 | ⚠️ desktop_fetch_auth_401 hadToken=true tokenSource=cached willRetry=true → POST /wham/statsig/bootstrap |
| 00:52:33.001 | ⚠️ auth_status_result authMethod=chatgpt hasToken=false nullReason=auth_token_missing refreshToken=true tokenExpiryState=missing |
| 00:52:33.046 | ⚠️ sa_server_request_failed ... status=401 url=/wham/statsig/bootstrap ({"detail":"Unauthorized"}) |
| 00:52:33.610 | ⚠️ desktop_fetch_auth_401 hadToken=false skipRetryReason=no_token_attached willRetry=false |
| 00:52:33.613 | ⚠️ 401 again on /wham/statsig/bootstrap |
| 00:52:34.167–34.170 | ⚠️ 401 again on /wham/statsig/bootstrap |
| 00:52:38 → 00:59:11 | No further activity except bundled_plugins_reconcile_skipped_features_unavailable reason=focus (~6.5 min). Window stays blank. No retry, no error surfaced. |
| ~00:59:11 | User force‑killed all Codex processes |
| 01:00:07 | Fresh launch → loaded normally, signed in, projects visible |

Note: the window‑context selected the remote‑ssh transport (mustafar.home.arpa) as
its app‑server, but the connection that actually initialized was hostId=local. Unclear
whether the remote selection contributed; flagging it in case the "selected transport"
vs "initialized transport" mismatch is relevant.

---

4. Key log evidence (verbatim)

2026-07-01T00:52:32.517Z info [electron-message-handler] [statsig-refresh-diagnostics] React root render requested rendererWebContentsId=1 rendererWindowVisible=true windowType=electron
2026-07-01T00:52:32.825Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=true skipRetryReason=null target="POST https://chatgpt.com/backend-api/wham/:param/:param" tokenSource=cached willRetry=true
2026-07-01T00:52:33.001Z warning [AppServerConnection] app_server_connection.auth_status_result authMethod=chatgpt cacheWrite=null hasToken=false nullReason=auth_token_missing refreshToken=true tokenExpiryState=missing
2026-07-01T00:52:33.046Z warning [electron-message-handler] sa_server_request_failed attachAuth=true attachIntegrityState=true errorMessage={"detail":"Unauthorized"} method=post routePattern=/wham/statsig/bootstrap status=401 url=/wham/statsig/bootstrap
2026-07-01T00:52:33.610Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=false skipRetryReason=no_token_attached target="POST https://chatgpt.com/backend-api/wham/:param/:param" tokenSource=cached willRetry=false
2026-07-01T00:52:34.170Z warning [electron-message-handler] sa_server_request_failed ... status=401 url=/wham/statsig/bootstrap
2026-07-01T00:52:38.089Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
... (repeats with no other activity until kill) ...
2026-07-01T00:59:11.932Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus

Full main‑process log is attached as codex-desktop-wedged-session.log.

---

5. Auth state at time of failure (redacted — NO token material included)

Read from ~/.codex/auth.json. No secrets are included in this report; only
metadata / expiries.

| Field | Value |
|---|---|
| auth_mode | chatgpt |
| OPENAI_API_KEY set | false |
| access_token exp (UTC) | 2026‑07‑02 03:14:19 ← still valid (~27h in future) at failure |
| id_token exp (UTC) | 2026‑06‑22 04:14:19 ← expired |
| refresh_token present | true |
| account_id present | true (value withheld — can be shared privately) |
| last_refresh (UTC) | 2026‑06‑22 03:14:34 (~9 days before the incident) |
| auth.json mtime (UTC) | 2026‑06‑22 03:14:34 (file untouched since last refresh) |
| Current time at failure (UTC) | 2026‑07‑01 01:02 |

Notable: access_token was not expired, yet the server 401'd it and the
refresh failed to produce a token. Possible server‑side session invalidation (e.g.,
re‑login elsewhere, token‑family rotation, or the 26.623.61825 → 26.623.9142.0 app
update). Whatever the cause, the client's handling — dropping to hasToken=false and
then never retrying while rendering a blank window — is the reportable defect.

The CLI's own codex login status (same CODEX_HOME) reports "Logged in using ChatGPT"
because it only reads auth.json and does not validate against the server — so the CLI
and the desktop app disagree about auth state.

---

6. Secondary findings (not the cause, but worth flagging)

  • ~/.codex/logs_2.sqlite is ~875 MB (917,557,248 bytes). Abnormally large local log

DB; appears to grow unbounded.

  • Stale CODEX_CLI_PATH in ~/.codex/config.toml points to

...\bin\aec6b7c6fcdfb66a\codex.exe, a hashed dir that no longer exists (current is
...\d8dfab353c0001dc\). Harmless but stale after updates.

  • New‑session desktop logs are 0 bytes (...-53708-t0-... and -t1- from the healthy

01:00 launch were both empty), so the healthy run produced no main‑process log lines in
that file — may indicate a logging path/flush issue on some launches.

---

7. Reproduction / expected vs actual

Steps: Launch Codex Desktop while the stored ChatGPT session is being rejected by the
backend (401 on /wham/statsig/bootstrap) and the token refresh fails.

Actual: Window opens and stays permanently blank; no error, no spinner, no retry.
Relaunching re‑focuses the wedged process. Only a full process kill recovers it.

Expected: On auth bootstrap failure, either (a) transparently retry with backoff,
(b) fall back to the still‑valid cached access_token, or (c) surface a visible
"couldn't sign in / please re‑authenticate" state instead of a blank window.

---

8. Workaround (for other users hitting this)

# Fully terminate every Codex process, then relaunch clean:
Get-Process Codex, codex -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep 2
Start-Process "explorer.exe" "shell:AppsFolder\OpenAI.Codex_2p2nqsd0c76g0!App"

If it still comes back blank with 401s in the log, re‑authenticate:
codex logout then codex login.

---

9. Attached files

  • codex-desktop-wedged-session.log — full main‑process log of the wedged 00:52 launch

(source: %LOCALAPPDATA%\Packages\OpenAI.Codex_2p2nqsd0c76g0\LocalCache\Local\Codex\Logs\2026\07\01\codex-desktop-bbe2b72a-f166-4885-b26e-55c726f16067-50788-t0-i1-005226-0.log).

---

<details>
<summary>Full main-process log — wedged 00:52 UTC launch (verbatim)</summary>

2026-07-01T00:52:26.984Z info Launching app agentRunId=null allowDebugMenu=false allowDevtools=false allowInspectElement=false buildFlavor=prod enableSparkle=false enableUpdater=true nodeEnv=undefined packaged=true platform=win32
2026-07-01T00:52:27.331Z info Appshot hotkey inactive configured=true enabled=true platform=win32
2026-07-01T00:52:27.335Z info [remote-connections/window-context] refresh_started previousConnectionCount=0
2026-07-01T00:52:27.336Z info [AppServerConnection] Initializing app-server transport
2026-07-01T00:52:27.336Z info [AppServerConnection] Starting app-server connection hostId=local transport=stdio
2026-07-01T00:52:27.336Z info [AppServerConnection] app_server_connection.state_changed cause=start_process connectionError=null currentConnectionId=null currentState=disconnected hasConnection=false hostId=local initialized=false initializeInFlight=false next=connecting pendingClientRequests=0 pendingInternalRequests=0 previous=disconnected reconnectAttempt=0 reconnectTimerScheduled=false restartInFlight=false targetConnectionId=null targetReadyState=null transport=stdio
2026-07-01T00:52:29.564Z info [remote-connections/window-context] load_completed savedRemoteConnectionCount=2 totalConnectionCount=2
2026-07-01T00:52:29.564Z info [WindowContext] [ssh-websocket-v0] selected app-server transport hostId=remote-ssh-codex-managed:mustafar.home.arpa
2026-07-01T00:52:29.565Z info [remote-connections/window-context] reconcile_completed creationFailureCount=0 nextConnectionCount=2 previousConnectionCount=0
2026-07-01T00:52:29.565Z info [remote-connections/window-context] refresh_completed autoConnectConnectionCount=1 codexManagedConnectionCount=2 discoveredConnectionCount=0 nextConnectionCount=2 previousConnectionCount=0
2026-07-01T00:52:29.945Z info [StdioConnection] stdio_transport_spawned argsCount=2 executablePath="C:\\Program Files\\WindowsApps\\OpenAI.Codex_26.623.9142.0_x64__2p2nqsd0c76g0\\app\\resources\\codex.exe" pid=29540 spawnCommand="C:\\Program Files\\WindowsApps\\OpenAI.Codex_26.623.9142.0_x64__2p2nqsd0c76g0\\app\\resources\\codex.exe"
2026-07-01T00:52:29.945Z info [AppServerConnection] Transport start success connectionId=1 hostId=local transport=stdio
2026-07-01T00:52:30.068Z info [AppServerConnection] Current reported app-server version: currentVersion=0.142.4 hostId=local
2026-07-01T00:52:30.069Z info [AppServerConnection] initialize_handshake_result durationMs=124 initializeRequestId=__codex_initialize__ outcome=success transportKind=stdio
2026-07-01T00:52:30.069Z info [AppServerConnection] Codex CLI initialized
2026-07-01T00:52:30.069Z info [AppServerConnection] app_server_connection.state_changed cause=post_initialize_connection_state connectionError=null currentConnectionId=1 currentState=connecting hasConnection=true hostId=local initialized=true initializeInFlight=false next=connected pendingClientRequests=0 pendingInternalRequests=0 previous=connecting reconnectAttempt=0 reconnectTimerScheduled=false restartInFlight=false targetConnectionId=1 targetReadyState=1 transport=stdio
2026-07-01T00:52:30.151Z info [IpcRouter] I am the router
2026-07-01T00:52:30.205Z info [window-manager] window main frame finished load appearance=primary hostId=local startupElapsedMs=95 webContentsId=1 windowId=1
2026-07-01T00:52:30.230Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:52:30.234Z info [window-manager] window ready-to-show appearance=primary hostId=local startupElapsedMs=125 webContentsId=1 windowId=1
2026-07-01T00:52:32.517Z info [electron-message-handler] [statsig-refresh-diagnostics] React root render requested rendererWebContentsId=1 rendererWindowAppearance=primary rendererWindowFocused=true rendererWindowId=1 rendererWindowVisible=true windowType=electron
2026-07-01T00:52:32.530Z info [electron-fetch-handler] codex-home request hostId=local params={"hostId":"local","origin":{"_events":{"render-process-gone":[null,null],"destroyed":[null,null,null,null,null,null,null,null,null,null,null,null,null],"unresponsive":[null,null]},"_eventsCount":31,"ipc":{"_events":{},"_eventsCount":1,"_invokeHandlers":{}},"navigationHistory":{}},"signal":{}}
2026-07-01T00:52:32.530Z info [AppServerConnection] response_routed broadcastFallback=false conversationId=null durationMs=1 errorCode=null hadInternalHandler=false hadPending=true method=remoteControl/status/read originWebcontentsId=1 requestId=b3e086b8-482c-4c84-85bf-0c33d5ba4043 targetDestroyed=false
2026-07-01T00:52:32.761Z info [wsl] eligible distro list listResult="NAME                   STATE           VERSION\n* Ubuntu                 Stopped         2\n  Fedora                 Stopped         2\n  docker-desktop         Stopped         2\n  Ubuntu-24.04           Stopped         2\n  openSUSE-Tumbleweed    Stopped         2"
2026-07-01T00:52:32.763Z info [AppServerConnection] response_routed broadcastFallback=false conversationId=null durationMs=0 errorCode=null hadInternalHandler=false hadPending=true method=account/read originWebcontentsId=1 requestId=59d76da0-3cf4-4911-90ea-badc5cc3c5ad targetDestroyed=false
2026-07-01T00:52:32.770Z info [AppServerConnection] response_routed broadcastFallback=false conversationId=null durationMs=7 errorCode=null hadInternalHandler=false hadPending=true method=fs/readFile originWebcontentsId=1 requestId=5b66f0da-29c7-4d7e-a8f7-fc13bf41bb6f targetDestroyed=false
2026-07-01T00:52:32.770Z info [electron-fetch-handler] codex-home request hostId=local params={"hostId":"local","origin":{"_events":{"render-process-gone":[null,null],"destroyed":[null,null,null,null,null,null,null,null,null,null,null,null,null,null],"unresponsive":[null,null]},"_eventsCount":31,"ipc":{"_events":{},"_eventsCount":1,"_invokeHandlers":{}},"navigationHistory":{}},"signal":{}}
2026-07-01T00:52:32.825Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=true skipRetryReason=null target="POST https://chatgpt.com/backend-api/wham/:param/:param" tokenSource=cached willRetry=true
2026-07-01T00:52:33.001Z warning [AppServerConnection] app_server_connection.auth_status_result authMethod=chatgpt cacheWrite=null hasToken=false nullReason=auth_token_missing refreshToken=true tokenExpiryState=missing
2026-07-01T00:52:33.046Z warning [electron-message-handler] sa_server_request_failed attachAuth=true attachIntegrityState=true errorCode=undefined errorMessage={"detail":"Unauthorized"} errorName=Error errorStack="Error: {\"detail\":\"Unauthorized\"}\n    at Object.postMessage (app://-/assets/vscode-api-D5f6BQ2W.js:1:5199)\n    at e.dispatchMessage (app://-/assets/vscode-api-D5f6BQ2W.js:1:6343)\n    at async JK (app://-/assets/app-main-CDVkM6Ux.js:47:207210)\n    at async Object.mutationFn (app://-/assets/app-main-CDVkM6Ux.js:47:218924)" hasRequestBody=true method=post rendererWebContentsId=1 rendererWindowAppearance=primary rendererWindowFocused=true rendererWindowId=1 rendererWindowVisible=true requestHeaderNames=["OAI-Language","X-OpenAI-Attach-Auth","X-OpenAI-Attach-Integrity-State","originator"] routePattern=/wham/statsig/bootstrap status=401 url=/wham/statsig/bootstrap
2026-07-01T00:52:33.392Z info [AppServerConnection] response_routed broadcastFallback=false conversationId=null durationMs=625 errorCode=null hadInternalHandler=false hadPending=true method=thread/list originWebcontentsId=1 requestId=e6dd81a7-876a-4549-893f-5533cef6cf79 targetDestroyed=false
2026-07-01T00:52:33.610Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=false skipRetryReason=no_token_attached target="POST https://chatgpt.com/backend-api/wham/:param/:param" tokenSource=cached willRetry=false
2026-07-01T00:52:33.613Z warning [electron-message-handler] sa_server_request_failed attachAuth=true attachIntegrityState=true errorCode=undefined errorMessage={"detail":"Unauthorized"} errorName=Error errorStack="Error: {\"detail\":\"Unauthorized\"}\n    at Object.postMessage (app://-/assets/vscode-api-D5f6BQ2W.js:1:5199)\n    at e.dispatchMessage (app://-/assets/vscode-api-D5f6BQ2W.js:1:6343)\n    at app://-/assets/vscode-api-D5f6BQ2W.js:1:6823\n    at Ae (app://-/assets/vscode-api-D5f6BQ2W.js:1:4739)\n    at U (app://-/assets/vscode-api-D5f6BQ2W.js:1:4802)\n    at async JK (app://-/assets/app-main-CDVkM6Ux.js:47:207210)\n    at async Object.mutationFn (app://-/assets/app-main-CDVkM6Ux.js:47:218924)" hasRequestBody=true method=post rendererWebContentsId=1 rendererWindowAppearance=primary rendererWindowFocused=true rendererWindowId=1 rendererWindowVisible=true requestHeaderNames=["OAI-Language","X-OpenAI-Attach-Auth","X-OpenAI-Attach-Integrity-State","originator"] routePattern=/wham/statsig/bootstrap status=401 url=/wham/statsig/bootstrap
2026-07-01T00:52:34.167Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=false skipRetryReason=no_token_attached target="POST https://chatgpt.com/backend-api/wham/:param/:param" tokenSource=cached willRetry=false
2026-07-01T00:52:34.170Z warning [electron-message-handler] sa_server_request_failed attachAuth=true attachIntegrityState=true errorCode=undefined errorMessage={"detail":"Unauthorized"} errorName=Error errorStack="Error: {\"detail\":\"Unauthorized\"}\n    at Object.postMessage (app://-/assets/vscode-api-D5f6BQ2W.js:1:5199)\n    at e.dispatchMessage (app://-/assets/vscode-api-D5f6BQ2W.js:1:6343)\n    at app://-/assets/vscode-api-D5f6BQ2W.js:1:6823\n    at Ae (app://-/assets/vscode-api-D5f6BQ2W.js:1:4739)\n    at U (app://-/assets/vscode-api-D5f6BQ2W.js:1:4802)\n    at async JK (app://-/assets/app-main-CDVkM6Ux.js:47:207210)\n    at async Object.mutationFn (app://-/assets/app-main-CDVkM6Ux.js:47:218924)" hasRequestBody=true method=post rendererWebContentsId=1 rendererWindowAppearance=primary rendererWindowFocused=true rendererWindowId=1 rendererWindowVisible=true requestHeaderNames=["OAI-Language","X-OpenAI-Attach-Auth","X-OpenAI-Attach-Integrity-State","originator"] routePattern=/wham/statsig/bootstrap status=401 url=/wham/statsig/bootstrap
2026-07-01T00:52:38.089Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:53:17.547Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:53:35.117Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:54:14.918Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:54:19.744Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:55:04.245Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus
2026-07-01T00:59:11.932Z info [bundled-plugins] bundled_plugins_reconcile_skipped_features_unavailable reason=focus

</details>

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #30039

Powered by Codex Action

tdmackey · 1 month ago

Update — likely trigger identified: enabling 2FA on the OpenAI/ChatGPT account

The reporter enabled two-factor authentication (2FA/MFA) on the OpenAI account right
around the time of this failure. That appears to be the trigger, and a follow-up check
sharpens the root cause:

  • The stored token was valid the whole time and still is. ~/.codex/auth.json was

never re-written across the incident and the subsequent recoveries — last_refresh
and the file mtime are both still 2026-06-22T03:14:34Z, and the access_token (exp
2026-07-02T03:14:19Z) is the same one that got 401'd during the wedge.

  • Clean restarts with that same token succeed. After a full process kill + relaunch,

the app authenticates, loads the account/projects, and renders normally — using the
identical on-disk token, with no silent refresh and no browser re-login.

Interpretation: enabling 2FA caused a brief server-side session-state change, and the
desktop app's startup happened to hit a transient 401 on
POST /wham/statsig/bootstrap during that window. Instead of retrying (or surfacing an
error / prompting re-auth), the app wedged permanently on a blank window — for ~6.5
minutes it logged nothing but bundled_plugins_reconcile_skipped_features_unavailable
reason=focus
. The fact that a clean restart with the same credentials works proves the
failure was recoverable and the client simply didn't recover.

Suggested repro: induce a transient 401 on the startup /wham/statsig/bootstrap
call (e.g., enroll the account in MFA at/around app boot, or otherwise briefly invalidate
the session server-side). Expected: transparent retry, cached-token fallback, or a visible
"couldn't sign in" state. Actual: indefinitely blank window, no retry, no error.

This also refines bug #2 in the original report: the auth_status_result
hasToken=false nullReason=auth_token_missing
after the failed refresh happened even though
a valid access_token was on disk — i.e. the failed refresh dropped the in-memory token
instead of falling back to the still-valid cached one.

jingtingyang1-ctrl · 8 days ago

I can reproduce the same auth bootstrap failure on Windows, but in my case fully terminating the app, resetting the MSIX package, and completing a fresh browser sign-in do not recover it. The desktop app returns to the sign-in loop within seconds.

Environment

  • OS: Microsoft Windows NT 10.0.26200.0 x64 (Windows 25H2, build 26200.9168)
  • Codex desktop MSIX: OpenAI.Codex 26.814.5517.0 x64, package status Ok
  • Bundled/app-server CLI: codex-cli 0.147.0
  • Auth method: ChatGPT
  • codex login status: Logged in using ChatGPT
  • ChatGPT in the browser works with the same account

No CODEX_ACCESS_TOKEN, OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_API_BASE, or CHATGPT_BASE_URL is set at Process, User, or Machine scope.

Clean reproduction

  1. Fully terminate all packaged Codex/ChatGPT processes.
  2. Back up ~/.codex/auth.json, config.toml, and desktop logs.
  3. Run Reset-AppxPackage for OpenAI.Codex_26.814.5517.0_x64__2p2nqsd0c76g0.
  4. Launch the app and complete browser-based ChatGPT sign-in.
  5. The app reports login success, but its first authenticated backend request receives 401; the app-server then reports that the auth token is missing and the sign-in loop resumes.

The reset was performed only after all app processes had exited. The issue reproduced immediately on the first post-reset launch.

Post-reset timeline (UTC, sensitive identifiers redacted)

2026-08-19T12:12:16.669Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=true target="GET https://chatgpt.com/backend-api/accounts/:param/settings" tokenSource=cached willRetry=true
2026-08-19T12:12:18.170Z warning [AppServerConnection] app_server_connection.auth_status_result authMethod=chatgpt hasToken=false nullReason=auth_token_missing refreshToken=true tokenExpiryState=missing
2026-08-19T12:12:18.468Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=false target="GET https://chatgpt.com/backend-api/wham/:param/:param"
2026-08-19T12:12:32.721Z info [electron-message-handler] account_login_completed success=true
2026-08-19T12:12:39.278Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=true target="GET https://chatgpt.com/backend-api/accounts/:param/settings" tokenSource=cached willRetry=true
2026-08-19T12:12:40.737Z warning [AppServerConnection] app_server_connection.auth_status_result authMethod=chatgpt hasToken=false nullReason=auth_token_missing refreshToken=true tokenExpiryState=missing
2026-08-19T12:12:41.234Z warning [electron-fetch-wrapper] desktop_fetch_auth_401 hadToken=false target="GET https://chatgpt.com/backend-api/wham/:param/:param"

The auth.json modification time is exactly the successful login-completion time (2026-08-19 12:12:32Z). It has the expected ChatGPT auth structure, contains a refresh token, and its access-token JWT expiry was still in the future. Token values, email, and account ID are deliberately omitted.

Across 10 affected launches before the package reset, the desktop logs contained 88 desktop_fetch_auth_401 events. The reset and clean re-login produced the same sequence.

Expected vs actual

Expected: after browser sign-in succeeds, the desktop app should retain/refresh the token and attach it to ChatGPT backend requests.

Actual: login completes successfully and writes the auth cache, the next backend call returns 401, the app-server transitions to hasToken=false / auth_token_missing, and the desktop app requests sign-in again.

This looks like an Electron/app-server token handoff or refresh/cache failure rather than an invalid local login file. Raw logs are available for private support review, but I am not attaching them publicly because they may contain authentication material or account identifiers.