Repository navigation
ChatGPT/Codex Desktop main window renders empty (or "Work" shell with endless spinner) on first load after every update since 26.901.2854.0; only a DevTools Page.reload fixes it #43960
Description
What version of the Codex App are you using (From “About Codex” dialog)?
26.901.6511.0 (MSIX package OpenAI.Codex_26.901.6511.0_x64__2p2nqsd0c76g0). Also reproduced on 26.901.2854.0 (Sept 3) and 26.901.5280.0 (Sept 5). Embedded Chromium 152.0.7977.83, bundled codex-cli 0.153.4.
What subscription do you have?
ChatGPT Pro
What platform is your computer?
Microsoft Windows 11 Pro 25H2, build 10.0.26200, x64. Dell Precision 7920 (Xeon Silver 4110, NVIDIA Quadro P5000, driver 32.0.15.8278). Single 2560x1080 display, 100% scaling. No proxy, no VPN on the default route (WireGuard and Tailscale adapters present but not default).
What issue are you seeing?
Since the update to 26.901.2854.0 on Sept 3, 2026, the main window never renders correctly on its first load. Every launch ends in one of two states:
- Fully empty window: only the gradient background and the min/max/close buttons. The DOM of
app://-/index.htmlhas ~23 elements:#rootcontains only the pre-mounted (inert/invisible) pricing overlay, nothing else.body.innerTextis empty. - "Work" shell without composer: the sidebar renders (header shows "Work", projects list), the center shows the OpenAI logo spinner forever, projects show "Carregando chats"/"Loading chats" forever, and there is no message composer (
document.querySelectorAll('input, textarea, [contenteditable]')= 0).
Everything else is healthy in the app's own logs (LocalCache\Local\Codex\Logs\...): all processes Responding=True, no crash, no render-process-gone, app_server_connection reaches initialize_handshake_result outcome=success in ~1 s, getAuthStatus / account/read / model/list / config/read all answer with errorCode=null in < 250 ms, [chatgpt-account-lookup] completed ... authenticatedAccountPresent=true result=succeeded, window main frame finished load and ready-to-show fire normally, and [startup][renderer] app routes mounted after ~6700ms is logged for the primary window.
What the renderer console says on load (captured through CDP Runtime.consoleAPICalled):
Matched leaf route at location "/" does not have an element or Component.
This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.
The only thing that fixes it is reloading the same webContents: launching the app with --remote-debugging-port=N and sending Page.reload {ignoreCache:true} to the app://-/index.html target. After the reload the DOM goes from ~23 elements / 0 text / 0 inputs to ~1750 elements / ~1500 chars / 2 inputs, the header switches from "Work" to "ChatGPT", projects and recent conversations load, and the composer appears. The reload also triggers main-process work that never happened in the broken state: bundled_plugins_reconcile_started reason=startup, browser_use_iab_backend_startup_started, chatgpt_conversation_updates_subscription_mounted, and app/installed + app/read requests to the app-server. In the broken state main keeps logging bundled_plugins_reconcile_skipped_features_unavailable reason=focus on every focus.
On Sept 3 a single reload was enough and subsequent normal launches worked. Since Sept 5, every normal launch (7 of 7 on Sept 5, again on Sept 8) is broken again; only an instance kept running with the debugging port open is usable.
Two other warnings appear at every start, in working and broken instances alike, so they are probably unrelated: Failed to start the Artifact Session host errorMessage="Artifact Session host Unix-socket transport is not available on Windows." and two fs/readFile requests failing with os error 3 (path not found) right after startup.
What steps can reproduce the bug?
Feedback ID: no-active-thread-01a08355-ffb9-7ef0-b1ca-470e3be31017
What is the expected behavior?
The main window renders the ChatGPT UI (sidebar, conversations, projects, composer) on the first load, without needing a manual reload through the debugging protocol.
Additional information
- Package update timeline on this machine: 26.901.1978.0 -> 2854.0 (Sept 3) -> 4073.0 (Sept 4) -> 5003.0 and 5280.0 (Sept 5) -> 6511.0 (Sept 8). The bug has been present in every build since 2854.0.
- Logs from all three builds (with paths anonymized) and the exact CDP transcript of a broken load + reload are available on request.
- Looks related to Codex Desktop for Windows 26.519.2081.0 turns blank white after ChatGPT login #23795, Windows Desktop launches ChatGPT.exe background processes but no UI/window appears #41075, [Windows][26.820.9563.0] ChatGPT Desktop launches headless after upgrade from Classic; no renderer/window created #41179 (blank/headless window after update) and Windows desktop renderer reloads and resets active ChatGPT/Codex conversation after latest update #32917 (renderer reload/state).
- Workaround I am using: a PowerShell script that launches the app with a random high
--remote-debugging-port, sendsPage.reloadover CDP and leaves the instance running. This is not acceptable as a permanent state because it leaves a debugging port open on the machine.
Activity
github-actions commentedon Sep 9, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
kylerjkirk commentedon Sep 26, 2026
Same bug on 26.924.1866.0 (MSIX OpenAI.Codex_26.924.1866.0_x64__2p2nqsd0c76g0, build 11431, commit 97cf4a3c), Windows 10 Pro 22H2 (19045), NVIDIA RTX 2080.
It started with the update from 26.917 (build 10954). My last launch on 26.917 loaded normally. Every launch on 26.924 failed.
Same fingerprints as the original report:
Matched leaf route at location "/" does not have an element or Componentname=app_start outcome=failure reason=timeoutat about 122 s. Marks reachsettings_ready(about 4 s) and never reachshell_visibleorhome_visible.thread/list,thread/read,model/listorskills/list. It only seesinitialize,experimentalFeature/enablement/setandremoteControl/enable.bundled_plugins_reconcile_skipped_features_unavailableon every failed launch.~/.codex/.codex-global-state.jsondid not help.Your Page.reload workaround fixes it here too. I launched with
--remote-debugging-port(127.0.0.1) and sentPage.reload {ignoreCache:true}toapp://-/index.html. The DOM went from 55 elements, no text and no inputs to 3,287 elements with the composer. That launch loggedapp_start outcome=successat 6.2 s (home_visible5.4 s,sidebar_ready6.2 s), followed bythread/listandthread/read.Separate from #48216: that one reaches
thread/listandthread/readand then fails onConversation state not found. In my failed launches the renderer never sendsthread/listat all.A10nEsK commentedon Sep 27, 2026
@rmacx @kylerjkirk — fuller independent Windows cold-start reproduction, with a controlled test of the startup gate. This was tested on a different installation running Windows Store/MSIX Stable
OpenAI.Codex 26.924.2738.0(bundled app-server 0.158.0-alpha.2.1). It is evidence about this installation; I cannot establish that every build in the original report fails through the same code path.Failure signature
On an ordinary cold launch,
app://-/index.htmlfinished loading but the primary window remained on the spinner. The React startup state was fulfilled, the route was initialized and idle, and account feature access was allowed.The main-process log already had the app-server version, initialization, and connection before the primary frame finished loading: 08:27:06.860 (version), .861 (initialized), .864 (connected), .867 (primary frame finished loading). In the renderer,
appServerVersion$remained unset and the host state initially remaineddisconnected.Direct inspection of the renderer state showed gateway OAuth readiness returning
loadingbecause the app-server-version dependency was null. The query cache had nogateway-oauth/readentry at all, so this was not a gateway request that had been sent and left pending.Controlled checks
connecteddid not recover the UI.appServerVersion$to the exact version already reported by the app-server created the internalgateway-oauth/readquery, which reachedsuccessin about 250 ms. This isolates the missing version as a prerequisite for the request; that state-injection probe by itself did not independently verify that the full UI had mounted.{type: "ready", initializationOnly: true}message caused the initialization snapshot to be delivered again. The interface began mounting within about one second, without a page reload or a fabricated version value; the gateway query also reachedsuccess.Page.reloadin the same process also restored the interface. Closing and cold-starting Stable reproduced the spinner.Likely mechanism and scope
Inspection of the packaged flow is consistent with an initialization-snapshot race: the renderer stores the version only when it handles
codex-app-server-initialized; the main process sends initialization state in response to rendererready; and the desktop-message buffer does not retain this event before the general renderer handler subscribes. If the snapshot arrives in that gap, gateway readiness can remainloadingindefinitely. Replayingreadyis a direct recovery for this installation.This is strong causal evidence for the immediate blocker on this machine. The event-order explanation is supported by the packaged code and recovery test, but has not been confirmed as the upstream root cause by a maintainer.
This appears closely related to the first-load/reload symptom in this issue. It is a different failure stage from #48216's successful
thread/list/thread/readcalls followed byConversation state not found: in this reproduction, the primary renderer is blocked before it creates the gateway query needed to proceed.Could the team check whether the initialization snapshot can arrive before the renderer handler is subscribed, and ensure that startup state is replayed or buffered so the primary window cannot remain on an indefinite spinner? No raw logs, screenshots, account identifiers, or personal filesystem paths are attached.
theodore-td commentedon Sep 27, 2026
Additional reproduction on 26.924.2738.0: initialization arrives before renderer listeners
Adding measured listener timing from this installation, consistent with the initialization-snapshot failure described above.
Environment
Symptoms and isolation
After closing and reopening, the entire primary window stays blank with a spinner, not just the conversation pane. This also reproduced in isolated cold launches using a separate Chromium profile and a copy of the current minimal Codex home, without restoring the historical backup. The backend initialization handshake and account lookup succeeded.
Five isolated cold-launch tests recovered visible UI after reloading the same renderer. Two further tests recovered visible content by requesting only the app's existing
{type:"ready", initializationOnly:true}snapshot, without page reload, backend restart, fabricated version values, credential changes, or deleting history.Measured event order in one snapshot-only test
An early diagnostic observer recorded selected window messages and message-listener registration; times below are milliseconds relative to page startup:
codex-app-server-initialized, version0.158.0-alpha.2.1; tracked application message listeners: 0windowMessageListenerisSnapshot=true, with receivers presentThe broad "any spinning element" check remained true in that instrumented run, so this establishes escape from the empty-window state, not that every background task finished. In the other snapshot-only run the spinner check became false. The isolated profiles can still require Windows sandbox setup; full chat functionality and restored-history behavior were not acceptance-tested.
Likely mechanism / requested fix
Local renderer inspection found the app-server version unset and gateway OAuth readiness stuck in
loading. Read-only inspection of the installed message path is consistent with an early initialization event being lost before subscribers exist. The checked message buffer did not retaincodex-app-server-initialized; requesting the existing snapshot after listener registration unblocked startup.Please investigate reliable replay/buffering of initialization state, an explicit snapshot request after receivers are installed, and bounded recovery rather than an indefinite spinner when version state is missing.
This is single-machine instrumented evidence, not a claim that all blank-window reports share the same cause; instrumentation can affect timing. No signed package files were patched. No raw logs, credentials, conversation contents, account identifiers, or personal filesystem paths are attached.
kyleisbased commentedon Sep 29, 2026
Independent confirmation of this failure signature, plus a launcher-integrated workaround that has been reliable across cold starts on a Windows 11 Store/MSIX installation.
Observed failure signature
On a hung cold launch, attached over CDP to the main window (
app://-/index.html):That matches the measurements in the report above exactly, including
innerHTML.length = 1236. The window is OS-responsive, the app-server completes its handshake and answersconfig/read,account/read,experimentalFeature/list,plugin/installedandskills/listin well under 50 ms each, and auth is valid — but the renderer never sends the follow-up work (nothread/list) and the UI stays on the spinner.Consistent with the analysis already posted in this thread, the renderer appears to lose the initialization snapshot because it arrives before the renderer's message listeners are registered, and is not replayed or buffered.
Two things I can confirm as not causal on my machine:
Matched leaf route at location "/" does not have an element or Component) fires on working and hung launches alike. It is a red herring, as noted above.config.tomlcontent does not control it. I A/B tested a comment-only config, a regenerated config, a deleted config, and an unchanged frozen config across repeated cold launches. A rendered run and a hung run ended up with byte-identical config files (same SHA-256). Removingconfig.tomloccasionally yields one working launch because it forces a fresh handshake — the same reason an external reload works — not because of its contents.A practical detail that cost me several failed attempts
The UI can take a long time to actually paint after the reload is issued. My first attempts polled for ~20 s and concluded failure, then gave up. Any verification loop needs to allow at least 25–30 s after
Page.reloadbefore deciding it did not work. Intermittency is also real: I measured roughly 3 of 4 cold launches hanging, consistent with the report above.Workaround
The approach is the one already described (launch with
--remote-debugging-port, then drive CDP). What I added, which is what made it dependable as a daily launcher rather than a manual recovery step:#rootchild count, spinner count, error-page detection) rather than a loose "is there any text" check. I had an early version that reported success against the browser's own error page because the error text exceeded the threshold, and a separate version that hung indefinitely because the CDP calls had no timeouts.PowerShell launcher. It reuses an existing session if one is already running, otherwise starts the app with the debug port and repairs it:
repair.mjs— targets the main window explicitly, re-requests the initialization snapshot first (works for some reporters, not on my build), then falls back to a reload, and allows 40 s for the UI to appear:probe.mjs— the pass/fail check. Only the main window counts; the app always has background windows (detached-window.html,avatar-overlayviainitialRoute) that legitimately never paint, and judging those makes the result meaningless:Measured results
With the version that fired the repair immediately after the debug port opened: 0 of 4 cold starts rendered. With the wait-then-retry version: 7 of 7 cold starts rendered, and after consolidating the scripts, a further 3 of 3.
Caveats
127.0.0.1while the app runs, which is not an acceptable permanent state.Thanks to everyone who documented the mechanism above — the listener-timing measurements in this thread are what made this reproducible rather than guesswork.