openai / openai/codex

Codex desktop (Windows): follow-up messages in existing threads never send

Open
#45,069 10 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug windows-os
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of the Codex App are you using (From “About Codex” dialog)?

26.908.40834

What subscription do you have?

Pro

What platform is your computer?

Windows 11 Home, build 26200 (x64); the machine is behind a TLS-inspecting proxy, but the proxy is not involved

What issue are you seeing?

Symptoms

  1. A new chat's first message sends normally. Every later message in that thread, and any message in an existing thread, spins forever. The text stays in the composer.
  2. No request reaches the app-server. The desktop logs show no turn/start, turn/steer or thread/queue/add, and no error.
  3. Sending to the same thread from the ChatGPT mobile app (remote control) works.
  4. Sending through the in-app send_message_to_thread tool also works.
  5. None of these helped: restarting the app, re-login, clearing the Electron Cache, Code Cache and GPUCache, switching followUpQueueMode between queue and steer, changing the model or permission mode, or using a different project folder.

Root cause analysis (runtime evidence)

The app was launched inside its package with --remote-debugging-port bound to 127.0.0.1. Non-pausing logpoints were set in webview/assets/app-primary-17b54400f32a.js and app-initial-d9bed9d614d8.js. The minified names below are from this build.

  1. The composer submit gate parks the message. At the start of Evr's submit handler the state was {submitDisabled:false, submitting:false, submitBlockReason:"loading-local-config"}. yvr.queueSubmit then queued it with isLocalConfigPending:true. None of the later steps ran (cvr, the turn coordinator, turn/start).

  2. Why isLocalConfigPending is true. Ygr() ends with composerMode==='local' && (localWorkspaceMaterialization==='loading' || …). The submit block context was:

    agentMode: guardian-approvals, isAgentModeLoading: false, isAgentModePending: false,
    windowsSandboxRequirement: null, isWindowsSandboxRequirementPending: false,
    localWorkspaceMaterialization: "loading", composerMode: "local", roots: ["D:\\Claude\\Kova"]
    

    Every other input was ready. The config/read, host and cwd data used by pvr() were all cached.

  3. Why materialization is loading. The D8 query options (managed-worktree-state) read TC = ["vscode","codex-home",{hostId}]. Because TC has no data and no error, D8 returns a disabled query keyed codex-home-loading. aQo then maps "no data" to "loading" indefinitely. Live query cache:

    ["vscode","codex-home","{\"hostId\":\"local\"}"]  status=pending fetchStatus=fetching fetchFailureCount=0 error=null
    ["vscode","codex-home"]                          status=pending fetchStatus=fetching fetchFailureCount=0 error=null
    ["git","local","managed-worktree-state","codex-home-loading","D:\\Claude\\Kova"]  status=pending fetchStatus=idle
    
  4. The startup codex-home request is never answered.

    • The renderer fetch client (sS.getInstance(), the vscode://codex/* bridge) still held 11 unresolved entries in pendingRequests about 30 minutes after launch.
    • The main process logged [electron-fetch-handler] codex-home request only during startup (six lines between +1.1 s and +14 s).
    • A fresh post('vscode://codex/codex-home', {"hostId":"local"}) from the same renderer returned in 2 ms with {"codexHome":"C:\\Users\\User\\.codex","worktreesSegment":"C:\\Users\\User\\.codex\\worktrees"}. The main handler (readCodexHomePaths) itself works; only the startup requests are lost.
  5. Why it never recovers. TanStack Query's Query.fetch reuses the in-flight retryer when state.data === undefined, even with cancelRefetch: true. Invalidation and refetch therefore keep waiting on the lost promise. There is no timeout on the bridge request.

  6. Confirmation. Running queryClient.cancelQueries({predicate: codex-home}) and then refetchQueries(...) turned both queries to success. D8 switched to ["git","local","managed-worktree-state","available",...], and the next desktop submit in an existing thread sent turn/start successfully (2026-09-12T15:48:34Z, conversation 01a0959a-…). This was the first one since 2026-09-11 16:18.

Startup timing correlation (not proven causal)

Times are milliseconds after Launching app:

Launch Result First codex-home requests First query-cache-invalidate broadcast
2026-09-09 works +3537, +3542 none in the first 40 s
2026-09-11 14:01 (d61b04e1) works +8872, +8905 +23185 (after avatar overlay loaded)
2026-09-11 16:35 (bbafcf82) fails +5219, +5237 +8568
2026-09-12 21:15 (430813af) fails +2565, +2573 +2893
2026-09-12 23:13 (4c766004) fails +2395, +2407 +3389

In every failing launch, an IPC query-cache-invalidate broadcast arrives about 1 s after the main window's first codex-home requests. It shows up in the main log as [IpcClient] Received broadcast but no handler is configured method=query-cache-invalidate. In the working launches it arrives much later or not at all during startup. This may be how responses get lost or mis-routed, but it has not been proven.

Ruled out

  • App-server: healthy. One codex.exe, fast responses, no queued items, SQLite quick_check ok.
  • Stream ownership and resume: the thread was resumed and this window was the owner.
  • Other submit gates: the goals feature (no goals), Windows sandbox readiness, and agent-mode or model-settings loading were all ready.
  • Remote-workspace gate: it would show a dialog, not a spinner.
  • Thread cwd: the \\?\ prefix and the specific project folder make no difference.
  • Machine environment: WSL (healthy), proxy or TLS, stale helper processes, OS updates.
What steps can reproduce the bug?

Feedback ID: 01a0959a-8824-7282-9ac2-59173f451f2d

What is the expected behavior?

Able to submit prompt to the previous session.

Additional information

Suggested fixes

  1. Add a timeout and retry to vscode://codex/* bridge requests, or reject pending requests on any window or IPC reset. Unanswered bridge requests should never hang forever.
  2. For codex-home, handle a stuck initial fetch with no data: cancel it, then refetch, instead of relying on cancelRefetch.
  3. Do not block the composer indefinitely when localWorkspaceMaterialization is loading. Fail open or show an actionable error after a timeout.
  4. Log bridge requests that stay pending longer than N seconds, with their URL, so this is visible in the desktop logs.

Workaround in use

Launch Codex with --remote-debugging-port=<port> via Invoke-CommandInDesktopPackage, then cancel and refetch the stuck codex-home queries through DevTools. This lasts only for that app session.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by inspecting webview/assets/app-primary-17b54400f32a.js and app-initial-d9bed9d614d8.js around the composer submit gate, codex-home bridge requests, and managed-worktree-state query. Reproduce the stuck pending request on Windows, then verify that an existing thread can submit a follow-up after the request recovers or fails visibly instead of spinning indefinitely.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, javascript
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.