Skip to content

Codex Desktop accepts prompt but UI stays stuck in Thinking; Stop fails and turn can become invisible after restart #24287

Open

Description

@winnal

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

Codex Desktop 26.519.41501 (CFBundleVersion 3044)

What subscription do you have?

ChatGPT Pro

What platform is your computer?

macOS 15.6.1 build 24G90
arm64
Apple M1 Max
64 GB RAM

Local app/runtime details observed from the installed app and local Sentry scope:

Bundle id: com.openai.codex
Electron: 42.1.0
Chrome runtime: 148.0.7778.97
Sentry release: codex@26.519.41501

What issue are you seeing?

Codex Desktop intermittently accepts prompts and continues executing backend work, but the Desktop UI loses reliable active-turn/session state. The visible chat can get stuck in Thinking, stop showing progress traces, show stale or missing turn state, or disagree with other UI surfaces about whether work is active.

I would consider this a major/critical issue, not a cosmetic UI bug, because the Desktop UI is the primary observability and control surface for active Codex execution. If trace visibility, active-turn state, and Stop/cancel state desynchronize, the user loses reliable control over active background work.

Important clarification: I have not observed an app crash, renderer crash, or automatic reload before this happens. The app can remain open. The issue appears to be that the renderer-visible session/turn/trace state becomes detached, stale, frozen, missing, or incompletely rehydrated while backend work may still be running.

The core bug:

  • the session/turn appears active or was already visibly active;
  • the UI can be stuck on Thinking;
  • the prompt bar may show an active turn with the Stop button, or in some /goal cases may incorrectly show Send while the goal bar still says the goal is actively pursuing;
  • no new progress traces appear, even while usage may continue decreasing;
  • Stop may be unavailable, misleading, or unresponsive;
  • the UI does not reliably reflect what the backend is actually doing.

This has happened intermittently for roughly a month. It appears random, but it may be more likely with long-running sessions/threads, trace-heavy turns, subagents/tools, compaction, multi-window use, /goal, or after a relogin/auth flow while the app remains open.

Observed failure modes

1. Prompt accepted, UI stuck in Thinking, Stop fails

Basic pattern:

  • I send a prompt.
  • The UI stays stuck on Thinking.
  • Pressing Stop does not stop the turn.
  • I am forced to quit/restart Codex Desktop manually.
  • After restart, the thread can look like my prompt was never sent, or it can show later assistant progress without showing the prompt and/or traces that happened while the UI was stuck.
  • Because the UI makes it look like the prompt was not accepted, I may resend the prompt.
  • Later recovered state proves the original prompt was accepted and the backend/agent had been working the whole time.
  • In previous occurrences, trying to recover by resending the prompt or forking the chat has produced errors along the lines of cannot find session / missing session.

2. Live trace/progress stream disappears

When this bug happens, it is not only the final assistant message or prompt bubble that can be affected. The live trace/progress stream itself can disappear.

Observed variants:

  • stuck Thinking with no traces shown, even though backend work appears to continue;
  • restart can remove traces that were previously visible;
  • for long tasks, the trace stream can randomly reattach later without restart;
  • sending a follow-up prompt has sometimes appeared to unstick/reconnect the trace stream.

3. /goal state split and multi-window rehydration failure

This also appears associated with the /goal feature, and the order of events matters.

Corrected repro order from one occurrence:

  1. I had already started the goal via a prompt in the original window.
  2. The goal was working normally.
  3. The original session UI was showing the prompt/goal progress traces normally.
  4. The prompt box was correctly showing the Stop button, indicating an active turn was running.
  5. Only after that, I tried opening the same session in a new Codex window.
  6. In the new window, the session failed to load or did not finish loading the active session state.
  7. At that point, the already-visible goal/prompt progress traces disappeared in both the new window and the original window.
  8. Both windows then looked as if the active turn/progress had been lost in the chat/trace area, and the prompt box showed Send instead of Stop. However, the goal bar above the prompt box still showed the goal as actively pursuing, not paused or stopped.
  9. After waiting some time, all of the traces that had previously been visible spontaneously appeared again, and the prompt box changed back to Stop.

This is different from the UI simply failing to show traces from the beginning. The traces and active Stop state were visible and working first. Opening the same session in a second window appears to have caused the Desktop UI to lose or detach the already-visible active turn/session state across all windows.

The especially strange part is that different parts of the same UI disagreed about whether work was active: the goal bar still showed an active pursuing-goal state, while the chat/trace area lost the active progress and the prompt box reverted to Send. That suggests a session/turn state split between the goal-level active state and the visible turn/trace/input state.

4. Multi-window active-session monitoring can freeze/detach visible progress across sessions

This is especially concerning when trying to monitor multiple active Codex sessions at once. My goal was to open each active session in its own Desktop window so I could watch each one progress, instead of manually switching between sessions inside a single window.

Observed behavior:

  • one existing window/session had been showing the active turn's persisted traces/progress correctly;
  • after trying to open active sessions in new windows, one of the windows hit the session loading/rehydration issue;
  • after that, visible progress across the sessions/windows appeared to become frozen or detached;
  • all of the sessions I had opened in new windows stopped showing new traces;
  • the backend presumably continued working in the background, but the Desktop UI stopped showing new trace/progress updates;
  • this makes the UI unreliable as a monitor for active work, because it can show no progress even while work may still be running.

This may be connected to very long sessions/threads. These sessions are long-running and trace-heavy, and it is starting to look possible that the app is failing to consistently load or rehydrate long session state unless I completely quit and restart the app.

5. Confirmed active backend usage while UI is frozen

This now appears confirmed as active backend execution with a frozen/detached Desktop UI.

Across multiple active sessions:

  • the UI shows the sessions as Thinking;
  • the prompt box shows the Stop button, indicating an active turn;
  • no new progress traces or activity are visible in the app;
  • the visible state appears frozen;
  • however, my usage dashboard is actively decreasing while this is happening.

That strongly indicates Codex is still executing and using model resources in the background, but the Desktop app is not showing any of the activity, traces, or progress. The issue is not simply that the model stopped or that the turn is idle. The backend appears active while the UI is detached from the running turn state.

Concrete evidence from one occurrence

After restart/recovery, the visible history showed that the original stuck turn had actually continued doing work. It showed status/progress like:

Steered conversation
The previous commit-boundary reviewer handle is not available in this resumed tool session, so there’s no valid approval artifact to consume. A new prompt delta just arrived too; I’m checking it against the already registered EK-DOCS-SYNC delta before I touch any gate state.

Explored 1 file, ran 2 commands
The repeated EK-DOCS-SYNC directive is already represented in the repo-local prompt-delta artifact and successor proof: full docs-state backfill, coverage matrix, canonical docs, and explicit forbidden actions are all present. I’m going to have the commit-boundary reviewer independently verify that duplicate/newest prompt is covered before approving the commit boundary.

Spawned 1 agent

Ran 3 commands
The reviewer is running while I keep my side read-only. One local inspection hit a harmless parsing assumption in VALIDATION.json; I’m not treating that as a repo failure, just as a cue to use the file’s actual schema when refreshing validation later.

The independent commit-boundary gate is approved with no findings, including the repeated EK-DOCS-SYNC directive check. I’m closing that reviewer and recording the gate outcome into repo-local artifacts/state before moving to commit approval.

From the user perspective before the manual restart, the app was simply stuck in Thinking, Stop did not work, and I could not see that work. I resent the prompt because the UI made it appear as if the prompt had not been sent.

Impact

  • Active agent work may continue while the UI appears frozen, stale, or detached. Usage can continue decreasing while no traces/progress are visible.
  • The user cannot reliably observe what Codex is doing.
  • The user cannot reliably determine whether a turn is active, stopped, detached, or invisible.
  • Stop/cancel may be unavailable, misleading, or unresponsive.
  • The visible chat history can be misleading after restart.
  • Duplicate prompts can be created because the original prompt is hidden or appears unsent.
  • Resend/fork recovery paths can hit missing-session style errors.
  • Long-running workflows with subagents/tooling can be duplicated, conflicted, or left running invisibly.
  • Multi-window monitoring of active sessions becomes unreliable because opening/loading one session can appear to freeze or detach visible progress across windows.

For an agentic desktop app that can run tools, spawn agents, and work on repositories, reliable active-turn state, trace visibility, and cancellation are core safety/control surfaces. If those desynchronize, the app becomes unsafe/unreliable for serious long-running work.

What steps can reproduce the bug?

I do not have a deterministic repro yet. Observed patterns:

Basic stuck Thinking / invisible turn path

  1. Use Codex Desktop on macOS during a long-running local workspace thread.
  2. Keep the app open. In some cases this may happen after a relogin/auth flow.
  3. Send a prompt.
  4. The UI remains stuck on Thinking after the prompt.
  5. Try pressing Stop. It does not stop the turn.
  6. Manually quit/restart Codex Desktop.
  7. Reopen the thread.
  8. The prompt/trace may be missing or partially recovered, even though later state shows the agent had been executing the prompt.
  9. If the prompt is resent because it looks unsent, it may later appear as a steered/duplicate continuation, or recovery actions like forking can hit missing-session errors.

/goal / second-window rehydration path

  1. Start a /goal turn via prompt.
  2. Let it run normally in the original window.
  3. Confirm traces/progress are visible and the prompt box shows Stop.
  4. Open the same session in a new Codex Desktop window.
  5. The new window fails to load or does not finish loading the active session state.
  6. Already-visible traces disappear in both windows.
  7. The goal bar still shows actively pursuing, but chat/trace state disappears and the prompt box may show Send instead of Stop.
  8. After waiting, traces may spontaneously reappear and the prompt box may return to Stop.

Multi-window active-session monitoring path

  1. Have multiple long-running active sessions.
  2. Open each session in its own Desktop window to monitor progress.
  3. One or more windows fail to load/rehydrate active session state completely.
  4. Visible progress traces across sessions/windows stop updating or appear frozen/detached.
  5. Backend work may still be running, but the UI no longer reliably shows progression.

Local state observations

Sanitized local state observations from the same app session:

  • Local Sentry scope had active app-state snapshots during the session.
  • Breadcrumb counts included:
    • method=turn/start: 2
    • method=turn/steer: 1
    • Item not found in turn state: 2
    • app_state_snapshot: 26
  • App-state snapshots repeatedly included active/streaming mismatch indicators:
    • thread_count_active: 4
    • thread_count_streaming_owner: 3
    • thread_count_streaming_without_role: 1
    • thread_count_streaming_without_active_runtime: 2-3
    • thread_count_with_inflight_turn: 1-2
    • inflight_turn_count: 1-2
    • browser_use_active_turn_route_count: 1-2

I am not claiming this is the same as reports involving a confirmed crash/reload, placeholder rebinding, or thousands of Item not found in turn state errors. The observed user-facing bug here is: prompt accepted and executed, UI stuck in Thinking or active-turn state becomes detached/frozen, Stop/Send state becomes misleading, and visible prompt/trace/session state is missing or misleading until restart or later rehydration.

What is the expected behavior?

If Codex Desktop accepts a prompt or continues a goal, it should durably and visibly associate that backend turn with the originating thread/session across windows.

Expected behavior:

  • The user prompt should remain visible after submission.
  • Assistant progress, tool calls, subagent activity, and traces should stream reliably while work is active.
  • Active turn state should be consistent between the goal bar, chat/trace area, and prompt box.
  • Opening the same session in another window should not detach or clear traces in the original window.
  • Opening multiple active sessions in separate windows should not freeze visible progress streams across sessions.
  • Stop should reliably cancel the backend turn or show why it cannot.
  • If the renderer/thread UI loses ownership of an active backend turn, the app should show a recovery/reattach state instead of generic stuck Thinking or misleading Send/Stop state.
  • Resending or forking should not produce missing-session errors or duplicate/steered turns because of hidden accepted prompts.
  • Long sessions should either load/rehydrate reliably or show an explicit loading/recovery state that does not erase visible active traces.

Additional information

This seems like a session/turn state ownership or trace-stream subscription problem between the Desktop UI and the backend/app-server. The backend appears to accept and execute prompts, but the UI can fail to show the submitted prompt, active stream, tool traces, goal/turn alignment, and cancellation state.

The main issue is not one exact repro path. It shows up through /goal, multi-window session opening, long-running turns, restarts, and sometimes follow-up prompts. The common failure is that the Desktop UI does not reliably and consistently show the real active state, progress, and trace stream for running sessions, especially long sessions.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    app-serverIssues involving app server protocol or interfaces
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on May 24, 2026
  2. winnal commented on May 24, 2026

    @winnal
    Author

    Additional detail about the visible trace/progress stream:

    When this bug happens, it is not only the final assistant message or prompt bubble that can be affected. The live trace/progress stream itself can disappear.

    Observed variants:

    1. Stuck Thinking with no traces shown

      Sometimes after I send a prompt, the UI gets stuck on Thinking and none of the traces/steps/progress are shown, even though the backend appears to be working.

    2. Restart can remove traces that were previously visible

      After manually quitting/restarting the app, the reopened thread can be missing parts of the thread that were previously present. In particular, if I send a prompt during an active turn and the app bugs out, then after restart the entire previous turn's traces can be gone from the visible UI.

    3. Trace stream can randomly reattach later without restart

      For long tasks, Codex normally shows progress/traces continuously during the turn. When the bug happens, it may show only Thinking and nothing afterward for a long time. If I wait an extended time, the UI can randomly resume showing traces again before the turn finishes.

    4. Follow-up prompt can sometimes unstick the trace stream

      In at least one occurrence, I sent another follow-up prompt while it was stuck, and that appeared to unstick the UI: the thinking/progress traces started showing again.

    This makes the bug feel like a live turn trace/session subscription or ownership desync. The backend work can continue, but the renderer-visible thread can stop receiving or rendering the active turn's trace events. Later, the UI may reattach spontaneously or after another prompt, but restart can also cause previously visible traces to disappear from the reconstructed thread view.

  3. MisterRound commented on May 24, 2026

    @MisterRound

    This is essentially the same thing I'm seeing in my issue #24263

  4. jshaofa-ui commented on May 24, 2026

    @jshaofa-ui

    title: "Codex Desktop accepts prompt but UI stays stuck in Thinking; Stop fails and turn can become invisible after restart"
    issue: #24287
    repo: openai/codex
    type: bug-fix
    area: app, session, app-server
    competition: low (3 comments, but no solution proposed)
    quote: $1,500-$2,500

    Complete Solution

    Root Cause Analysis

    This is a session/turn state ownership desync between the Codex Desktop UI (Electron renderer) and the backend/app-server. The core issue:

    1. Prompt accepted but UI loses ownership: The backend accepts and executes the prompt, but the UI's turn subscription fails to receive or render the prompt bubble, assistant progress, and tool traces
    2. Stop fails: The Stop button can't cancel because the UI doesn't have a valid reference to the active turn
    3. State invisible after restart: The thread's prompt/trace state is not durably associated with the originating thread, so restart shows misleading or missing history

    Key evidence from Sentry breadcrumbs:

    • thread_count_active: 4 but thread_count_streaming_owner: 3 — one active thread has no streaming owner
    • thread_count_streaming_without_role: 1 — a streaming thread has no role assigned
    • thread_count_streaming_without_active_runtime: 2-3 — streaming threads with no active runtime
    • Item not found in turn state: 2 — turn state lookup failures

    Fix — Three-Layer Approach

    Layer 1 — Turn ownership reconciliation (primary fix):

    // In app-server's turn management (Rust)
    // When a prompt is accepted, ensure the turn is durably linked to its thread
    // BEFORE any streaming begins
    
    fn handle_prompt(thread_id: &str, prompt: Prompt) -> Result<TurnId> {
        // 1. Create turn record in the thread's durable store FIRST
        let turn = Turn::new(thread_id, prompt);
        self.store.save_turn(&turn)?;  // Durable write before streaming
        
        // 2. THEN start the backend execution
        let turn_id = turn.id.clone();
        self.backend.execute(turn_id.clone(), prompt);
        
        // 3. Subscribe the UI to the turn stream
        self.ui.subscribe(thread_id, turn_id.clone());
        
        Ok(turn_id)
    }

    Layer 2 — Stop/cancel reliability:

    // In the Desktop UI's Stop handler
    async handleStop() {
        // Get the current turn_id from the durable store, not just in-memory state
        const turnId = await this.store.getActiveTurnId(this.threadId);
        if (!turnId) {
            // Show recovery UI instead of silently failing
            this.showRecoveryState("No active turn found. Checking backend state...");
            const backendTurn = await this.appServer.findActiveTurn(this.threadId);
            if (backendTurn) {
                // Re-attach UI to the backend turn
                await this.reattachToTurn(backendTurn);
            }
            return;
        }
        await this.appServer.cancelTurn(turnId);
    }

    Layer 3 — Recovery/reattach state:

    // When the UI detects it has lost ownership of an active turn
    async detectAndRecover() {
        const localActive = await this.store.getActiveTurns(this.threadId);
        const backendActive = await this.appServer.getActiveTurns(this.threadId);
        
        // Find turns that exist in backend but not in UI
        const orphanedTurns = backendActive.filter(
            bt => !localActive.some(lt => lt.id === bt.id)
        );
        
        for (const orphaned of orphanedTurns) {
            // Show a recovery banner
            this.showRecoveryBanner({
                type: 'orphaned_turn',
                turnId: orphaned.id,
                message: 'An active turn was found that is not visible in the UI. Click to re-attach.',
                action: () => this.reattachToTurn(orphaned)
            });
        }
    }

    Testing Strategy

    • Unit test: verify turn is durably stored before streaming begins
    • Integration test: simulate UI crash during active turn, verify recovery on restart
    • Edge case: verify Stop works even when UI has lost turn ownership
    • Regression test: verify normal turn flow (prompt → stream → response) is unaffected

    Files to Change

    1. codex-rs/app-server-daemon/src/turn_manager.rs — add durable turn storage before streaming
    2. app/src/turn-state-manager.ts — add recovery/reattach logic
    3. app/src/stop-handler.ts — use durable turn reference instead of in-memory

    Impact

    • Prompts are durably associated with their originating thread
    • Stop button reliably cancels the backend turn or shows recovery state
    • Orphaned turns are detected and recoverable after restart
    • No duplicate prompts from invisible accepted prompts
  5. winnal commented on May 24, 2026

    @winnal
    Author

    Additional detail: this also appears associated with the /goal feature, and the order of events matters.

    Corrected repro order:

    1. I had already started the goal via a prompt in the original window.
    2. The goal was working normally.
    3. The original session UI was showing the prompt/goal progress traces normally.
    4. The prompt box was correctly showing the Stop button, indicating an active turn was running.
    5. Only after that, I tried opening the same session in a new Codex window.
    6. In the new window, the session failed to load or did not finish loading the active session state.
    7. At that point, the already-visible goal/prompt progress traces disappeared in both the new window and the original window.
    8. Both windows then looked as if the active turn/progress had been lost in the chat/trace area, and the prompt box showed Send instead of Stop. However, the goal bar above the prompt box still showed the goal as actively pursuing, not paused or stopped.
    9. After waiting some time, all of the traces that had previously been visible spontaneously appeared again, and the prompt box changed back to Stop.

    This is different from the UI simply failing to show traces from the beginning. The traces and active Stop state were visible and working first. Opening the same session in a second window appears to have caused the desktop UI to lose or detach the already-visible active turn/session state across all windows.

    The especially strange part is that different parts of the same UI disagreed about whether work was active: the goal bar still showed an active pursuing-goal state, while the chat/trace area lost the active progress and the prompt box reverted to Send. That suggests a session/turn state split between the goal-level active state and the visible turn/trace/input state.

    That makes the session state shown in the UI feel temporary or incompletely rehydrated: the persisted/streaming state seems to disappear from the renderer until whatever session/turn binding or trace stream loading finishes again. When it reattaches, the missing traces reappear as if they had been there the whole time.

    This still does not look like an app crash. The app remains open. The visible session state becomes inconsistent across windows, then later rehydrates.

  6. winnal commented on May 24, 2026

    @winnal
    Author

    Additional impact / multi-window observation:

    This is especially concerning when trying to monitor multiple active Codex sessions at once. My goal was to open each active session in its own Desktop window so I could watch each one progress, instead of manually switching between sessions inside a single window.

    What I observed:

    • one existing window/session had been showing the active turn's persisted traces/progress correctly;
    • after trying to open active sessions in new windows, one of the windows hit the session loading/rehydration issue;
    • after that, visible progress across the sessions/windows appeared to become frozen or detached;
    • I could no longer reliably see further progress traces in the UI;
    • the backend presumably continued working in the background, but the Desktop UI stopped showing new trace/progress updates;
    • this makes the UI unreliable as a monitor for active work, because it can show no progress even while work may still be running.

    This may be connected to very long sessions/threads. These sessions are long-running and trace-heavy, and it is starting to look possible that the app is failing to consistently load or rehydrate long session state unless I completely quit and restart the app.

    The concerning failure mode is: opening the same or other active sessions in additional windows can appear to detach or freeze the visible active-turn state across windows, leaving the user unable to tell what is currently running or whether Stop would work.

  7. winnal commented on May 24, 2026

    @winnal
    Author

    Core failure mode clarification:

    As of now, all of the sessions I opened in new windows are no longer showing any new traces. This is the main problem behind the different variants I have described.

    The core bug is:

    • the session/turn appears active;
    • the UI can be stuck on Thinking;
    • the prompt bar may show an active turn with the Stop button;
    • but no new progress traces appear;
    • the UI does not reliably respond or reflect what the backend is actually doing.

    So the issue is broader than one exact repro path. It shows up through /goal, multi-window session opening, long-running turns, restarts, and sometimes follow-up prompts, but the common failure is that the Desktop UI does not reliably and consistently show the real active state, progress, and trace stream for running sessions, especially long sessions.

    In other words: the app can have an active backend turn, but the renderer-visible session state/trace stream becomes detached, frozen, missing, or stale. That makes the app UI unreliable for monitoring active Codex work and for knowing whether Stop will actually work.

  8. winnal commented on May 24, 2026

    @winnal
    Author

    Severity note:

    I would consider this a major/critical issue, not a cosmetic UI bug.

    Reason: the Desktop UI is the user's primary control and observability surface for active Codex execution. When it stops showing real progress traces, shows inconsistent active state, or leaves the user unsure whether Stop will work, the user loses reliable control over active background work.

    Impact:

    • active agent work may continue while the UI appears frozen or stale;
    • the user cannot reliably observe what Codex is doing;
    • the user cannot reliably determine whether a turn is active, stopped, or detached;
    • the Stop control may be unavailable, misleading, or unresponsive;
    • users may resend prompts or open/fork sessions because the UI makes the active state unclear;
    • long-running repo workflows can be duplicated, conflicted, or left running invisibly.

    For an agentic desktop app that can run tools, spawn agents, and work on repositories, reliable active-turn state, trace visibility, and cancellation are core safety/control surfaces. If those desynchronize, the app becomes unsafe/unreliable for serious long-running work.

  9. winnal commented on May 24, 2026

    @winnal
    Author

    Additional confirmation: this now appears confirmed as active backend execution with a frozen/detached Desktop UI.

    Across multiple active sessions:

    • the UI shows the sessions as Thinking;
    • the prompt box shows the Stop button, indicating an active turn;
    • no new progress traces or activity are visible in the app;
    • the visible state appears frozen;
    • however, my usage dashboard is actively decreasing while this is happening.

    That strongly indicates Codex is still executing and using model resources in the background, but the Desktop app is not showing any of the activity, traces, or progress. The issue is not simply that the model stopped or that the turn is idle. The backend appears active while the UI is detached from the running turn state.

    This is the core reliability problem: active work can continue invisibly while the app UI is stuck and provides no usable observability.

  10. grizzithal commented on May 25, 2026

    @grizzithal

    I’m seeing the same failure mode on Codex Desktop as well.

    In my case, the important part is that the UI appears detached from an active backend turn rather than the turn simply being idle. The thread can remain stuck on Thinking, progress traces stop updating, and Stop either does not work or does not appear to reflect the actual backend state. I have also seen cases where the prompt/turn appears missing after restart even though later state suggests the backend accepted and continued executing it.

    My observed pattern:

    • Codex accepts a prompt in an existing long-running thread.
    • The UI stays on Thinking with no new trace/progress updates.
    • The prompt box may still show Stop, but pressing it does not reliably cancel the work.
    • Restarting the app may show missing or partial turn history.
    • In some cases, usage continues decreasing while the UI shows no visible activity, which suggests backend execution is still active.
    • Sending a follow-up prompt or waiting can sometimes cause the trace stream to reattach.

    This is especially risky because the UI makes it unclear whether a turn is actually running, stopped, detached, or invisible. From a user-control perspective, the problematic behavior is not just stale rendering; it is loss of reliable observability and cancellation for active agent work.

    I can provide app version/platform details and local diagnostics if helpful. Are there specific logs, Sentry scope values, or local state files that would be most useful to capture the next time this happens?

  11. 8 remaining items

  12. kumag36 commented on Jul 31, 2026

    @kumag36

    Additional Windows/Desktop data point (2026-08-01 JST):

    • Codex Desktop version: 26.721.11231.0 on Windows.
    • In a multi-thread project workflow, a background worker thread completed work but its terminal callback did not become visible/deliver to the coordinating thread while the target worker thread was not open.
    • This was observed repeatedly: opening/focusing that exact worker task was immediately followed by the pending callback being delivered. The instruction was not resent, and no duplicate execution was observed.
    • In an earlier occurrence, a standard cross-thread send remained unanswered for 24,303,264 ms. The PC had not slept, the same app-server process was still alive, and the stopped model transport count observed at that point was zero. Delivery completed immediately after Desktop/thread resume. The initial connection-loss trigger remains unverified.
    • This looks stronger than ordinary rendering lag because the coordinating workflow remained waiting for the callback until the target task was foregrounded, although the exact backend/renderer boundary is still unverified.

    Expected behavior: a terminal callback/event should be delivered independently of whether the target thread is currently visible or focused, or the client should automatically resume/reconcile the thread without requiring UI interaction.

    Temporary recovery observed locally: do not resend the instruction; foreground the exact target thread once. Fully restarting Desktop is a secondary recovery, but it risks losing visible trace continuity. I can provide sanitized timestamps/log excerpts privately if useful; no repository or conversation content is included here.

  13. Roland0511 commented on Aug 10, 2026

    @Roland0511

    Additional sanitized diagnostic data point from a case where this affected not only the renderer, but also the thread-reading projection and subsequent model-visible context.

    Environment

    • Codex Desktop: 26.803.41515 (build 6321)
    • Bundled/installed CLI: codex-cli 0.147.0
    • macOS 26.5.2 (build 25F84), arm64
    • Thread ID: 019fa27e-f0ea-7f71-9c78-de349bfd3365

    Sanitized timeline (UTC)

    1. 10:39:38.241 — ordinary turn A started, turn ID 019feb41-aee3-7923-a41a-1249815e9d33.
    2. 10:39:38.361 — the user message for turn A was persisted in the rollout.
    3. 10:40:12.460 — context compaction occurred while turn A was active.
    4. 10:40:20.843 — the assistant's final answer for turn A was persisted.
    5. 10:40:21.211 — task_complete was persisted for turn A.
    6. 10:43:57.609 — ordinary follow-up turn B started, turn ID 019feb45-a3e9-76e3-aa84-a0cba38f7546.
    7. 10:43:58.704 — the user message for turn B was persisted.
    8. 10:44:04.141 — an assistant commentary message for turn B was persisted.
    9. 10:44:22.062 — turn_aborted was persisted for turn B.

    After turn B was aborted:

    • Desktop no longer displayed either the already-completed turn A or the interrupted turn B.
    • A current read_thread call also omitted both turn IDs and jumped from an earlier completed turn to later turns.
    • Subsequent model-visible context behaved as if those messages had never happened; the agent could not recognize the missing question/answer until the raw rollout was inspected manually.
    • Fully quitting and restarting Codex Desktop did not restore the missing turns.
    • The raw rollout JSONL still contains the exact user and assistant message records, task_complete for A, and turn_aborted for B.
    • There is no thread_rolled_back event around this sequence.

    Conversation text, repository names, and local paths are intentionally omitted.

    This appears more severe than a trace-only rendering issue: an abort of the current turn seems able to make a previously completed turn disappear from the canonical thread projection used by all three consumers:

    1. Desktop transcript
    2. thread-reading API
    3. model-context reconstruction

    The durable rollout remains intact, so the likely failure boundary is replay/indexing/canonical-turn reconstruction, possibly involving the combination of compaction inside turn A followed by aborting turn B.

    Expected invariant: aborting turn B must not remove completed turn A, and UI, thread APIs, and model-visible context should converge on the durable rollout history.

  14. tonyzhu163 commented on Aug 10, 2026

    @tonyzhu163

    This seriously hurts usability of running long-horizon tasks. I'm not sure how this has been in place for several months now?

  15. ByteYue commented on Aug 11, 2026

    @ByteYue

    Adding a sanitized data point involving Codex Desktop, subagent-heavy work, and a remote Linux app-server.

    Environment

    • Codex Desktop client: 26.803.41515
    • Remote app-server: 0.147.0
    • App-server managed by a systemd user service
    • Multiple Codex tasks open
    • Long/tool-heavy subagent turn with compilation activity
    • Repository names, branches, user paths, prompts, thread IDs, and turn IDs omitted

    I observed two related state-reconciliation failure modes.

    Case A: app-server restart while subagent work existed

    The app-server service was terminated by systemd-oomd and automatically restarted.

    After the restart:

    • the old OS processes belonging to the subagent were no longer present
    • the affected child/subagent session was not present in the new app-server process's active state
    • the Desktop UI could still retain an apparently active/running representation
    • Stop/retry controls did not reliably correspond to a live backend turn or process

    The worktree and file modifications remained intact, but the live execution handle did not survive the service restart. The problematic part was not the loss of the OS process itself; that is expected after the whole service cgroup is killed. The problematic part was that the client did not reliably reconcile the stale running state into an explicit interrupted, failed, or recoverable state.

    Case B: stale running UI without an app-server restart

    A later occurrence happened after the restart, while the app-server remained continuously healthy.

    The Desktop UI showed a long-running command as active. At the time of inspection:

    • no matching compilation process existed in the Linux process table
    • server-side turn telemetry had reached a terminal model decision:
      • model_needs_follow_up=false
      • has_pending_input=false
      • needs_follow_up=false
    • the Desktop UI still presented the command/turn as running
    • a new user message remained visibly queued
    • pressing Stop generated a process/kill request, but there was no matching OS process to terminate
    • the service restart counter did not change during this occurrence

    A few minutes later:

    • the queued message was accepted as a new turn on the same child thread
    • the long context triggered automatic compaction at approximately 255k cumulative tokens
    • the follow-up turn subsequently emitted turn/completed

    This suggests that the backend/thread remained usable while the Desktop view temporarily retained stale active-turn/process state.

    Possible contributing pressure

    During the same general interval, another Desktop connection generated a burst of Git process/spawn and process/exited events, similar to the behavior reported in #26812. I did not capture an explicit slow-connection disconnect warning for this exact occurrence, so I am not claiming that outbound backpressure is the proven trigger. It may simply be an event-load or client-state-rehydration amplifier.

    Expected recovery behavior

    After a disconnect, app-server restart, missing terminal event, or unknown process handle, the client should ideally:

    1. Re-read the authoritative thread/turn status.
    2. Clear cached active-turn and running-process state if the server has no corresponding active object.
    3. Mark the previous execution as interrupted, lost, or detached.
    4. Make Stop idempotent and surface "process/turn no longer exists" rather than remaining stuck.
    5. Allow queued input to start a new turn or present an explicit reattach/retry action.
    6. Avoid silently retaining an active UI state solely because turn/completed was not observed on the original connection.

    I am not claiming that this is necessarily the same internal trigger as every reproduction in this issue. The user-facing state split, however, is very similar: backend state and Desktop-visible active/Stop/queue state can disagree for an extended period.

    I can provide a redacted event timeline and systemd journal summary if that would help triage.

  16. harryshawk commented on Aug 14, 2026

    @harryshawk

    Additional macOS Codex Desktop evidence matching this issue:

    Affected task/thread IDs:

    • 019fc246-0b10-75e2-acfe-d666c96cd246
    • 019fa4ea-80fe-79b3-afc0-689bb52f12ba

    Observed behavior:

    • The thread remains visually active as though it is still thinking.
    • A newly submitted message enters the queue and is shown as a steered message, but it remains there and never starts.
    • Pressing the black square End/Stop button does nothing; the apparent active turn cannot be ended.
    • This affects more than one thread.
    • Both the Mac and the Codex/ChatGPT application were recently fully power-cycled/restarted, but the condition remains.

    The UI therefore presents an active-turn state while neither End/Stop nor queued-message delivery works. This is not resolved by restarting the machine or application. Screenshots captured on 2026-08-14 show the queued Steer card and the unresponsive End/Stop control.

  17. harryshawk commented on Aug 15, 2026

    @harryshawk

    Additional macOS Codex Desktop reproduction (2026-08-14):

    Before restarting Codex, thread 019fa4ea-80fe-79b3-afc0-689bb52f12ba is responsive, while thread 019fc246-0b10-75e2-acfe-d666c96cd246 is not responding. This is thread-specific within the same running app rather than a general connectivity failure. Codex has not yet been restarted, so recovery has not yet been tested.

  18. AdiedX commented on Aug 16, 2026

    @AdiedX

    I'm seeing what appears to be a closely related issue in the current ChatGPT/Codex desktop app on macOS.

    Environment:

    • MacBook Pro 16-inch (2021)
    • Apple M1 Pro
    • 32 GB RAM
    • macOS Tahoe 26.2
    • ChatGPT Plus
    • Issue became very noticeable within the last ~24 hours, after a recent ChatGPT desktop update

    Thread session IDs:
    01a00856-d54e-7221-8669-c91b61e33172
    01a00348-8da0-7593-924d-02b0fdf60f6c

    The most obvious repro for me is starting work in a new desktop window/session:

    1. Open a new ChatGPT desktop window.
    2. Submit a substantial prompt, often using Goal mode / agentic work.
    3. The turn starts, but then abruptly stops or loses forward progress even though the task is clearly unfinished.
    4. If I paste/send the same prompt again, or otherwise nudge the conversation, it starts working normally.

    This is happening frequently enough that I now expect to have to submit the initial request twice.

    I've completely deleted the ChatGPT app, downloaded a fresh copy, and reinstalled it. The behavior persists.

    I'm also seeing a related failure after context compaction: the agent stops instead of continuing the active task and requires another user message to resume.

    This did not occur regularly for me previously and seems to have become significantly worse following the recent desktop update.

    ChatGPT desktop build number Version 26.810.52044

  19. prashantbhamu commented on Aug 19, 2026

    @prashantbhamu

    I reproduced this on Windows, and the failure is especially clear because I could compare the frozen Desktop renderer with the same task's persisted/backend state from another task.

    Environment

    • Codex Desktop: 26.814.5167.0 (x64)
    • Windows: 10.0.26200.0 x64
    • Model shown in the affected task: GPT-5.6 Sol, medium reasoning

    Sequence

    1. Started a new task from ChatGPT real-time voice.
    2. Ended the real-time voice session.
    3. The task window remained on Thinking with a spinner/Stop button and did not show further progress.
    4. Inspecting the same task from a separate Codex task showed that the underlying turns were already completed, while the affected window still looked active.
    5. Clicking Stop produced Failed to stop chat. Archiving also failed.
    6. Fully restarting Codex Desktop rehydrated the task correctly: Thinking disappeared and the previously missing final response became visible.
    7. Without using voice again, I typed a keyboard-only follow-up in that same recovered task.
    8. The bug reproduced: the affected window showed only the submitted prompt plus Thinking, with no progress messages.
    9. From a separate task, the backend reported a genuine inProgress turn and exposed multiple assistant commentary updates plus completed/in-progress tool executions. None of those updates appeared in the affected window.
    10. Sending a stop instruction through the underlying task service completed the turn and changed its backend status to idle, while the affected renderer had not provided reliable visibility/control.

    Important distinction
    This produced both variants:

    • stale UI says active after the backend has already completed (Stop and archive fail);
    • backend is genuinely active and producing commentary/tool progress, but the Desktop window does not stream or display those updates.

    The second variant reproduced with keyboard-only input after restarting the app. Voice was only involved in the original creation of the task, suggesting that a voice-originated task may retain a broken renderer/stream subscription across later text turns.

    Expected
    The task window should reattach to the persisted/live turn stream, show commentary and tool progress, clear Thinking on completion, and keep Stop/archive availability consistent with backend state.

  20. prashantbhamu commented on Aug 19, 2026

    @prashantbhamu

    Additional evidence after a full Windows PC restart:

    • The affected task still could not be archived from the Desktop UI.
    • The task's persisted status was fully completed/not running.
    • Attempting to archive the same task through the underlying Codex task service also failed, with the exact error:
    failed to archive session: thread-store internal error: failed to archive thread:
    The system cannot find the file specified. (os error 2)
    

    I then checked the obvious local targets. The session JSONL file exists, the ~/.codex/archived_sessions directory exists, and the task working directory exists. This suggests a stale or mismatched internal path/reference in the thread store rather than the main session file actually being absent.

    A full application restart and a full PC restart both failed to repair the archive operation. This extends the impact beyond renderer/stream desynchronization: the affected voice-originated task appears to retain corrupted or inconsistent thread-store metadata that prevents lifecycle operations such as archive.

  21. zmc1997 commented on Sep 2, 2026

    @zmc1997

    I am seeing this issue repeatedly on a newer macOS desktop build.

    Environment

    • ChatGPT desktop: 26.820.71523 (build 7226)
    • Bundled Codex CLI/app-server: 0.150.0-alpha.8
    • macOS 14.4.1, arm64

    Repeated behavior

    1. A long-running local workspace turn initially progresses normally and may emit reasoning, tool calls, and part of an assistant response.
    2. Output then stops indefinitely while Desktop continues to show the active Stop button.
    3. Waiting does not recover the response.
    4. Pressing Stop and sending a continuation prompt does not reliably resume the unfinished task.
    5. This has happened in multiple conversations recently, not as a one-off failure.

    In one recent occurrence, the turn had to be manually stopped after 9m42s. The task did not reliably continue after retrying in the same conversation.

    Expected behavior

    • After a bounded period with no response activity, Desktop should reconnect, retry, or transition the turn to a recoverable error state.
    • Stop should reliably interrupt the active turn and clear stale streaming state.
    • A follow-up continuation should resume from the last persisted completed item.
    • Desktop should reconcile the composer/Stop state with the actual backend turn state after interruption or reconnect.

    No thread IDs, raw logs, local paths, repository names, account details, screenshots, or project content are included in this comment.

  22. mdotk commented on Sep 17, 2026

    @mdotk

    Additional macOS reproduction with archive/unarchive and active-writer evidence (2026-09-18 NZST).

    Environment:

    • Codex Desktop 26.911.61220, build 9647
    • Bundled codex-cli 0.155.0-alpha.2.6
    • macOS, Apple Silicon

    Observed sequence from the desktop log and read-only thread APIs:

    1. A turn ran normally for about 17 minutes, then failed with Selected model is at capacity. Please try a different model.
    2. Archiving the task succeeded. Immediately afterward, the desktop attempted thread/resume; app-server correctly rejected it because the session was archived. The desktop logged heartbeat_automation_resume_failed with failureReason=thread_archived.
    3. Roughly 50 seconds later, the app issued thread/unarchive, resumed the task, and accepted a new turn/start.
    4. The new turn produced backend reasoning events, but the desktop composer remained stuck in Thinking; Send was unavailable and no usable Stop control was exposed.
    5. Read-only task status continued to report the new turn as inProgress, with no terminal error or completion.
    6. The desktop log contains no turn/interrupt request for this task. The user's attempted Stop action therefore never reached app-server.
    7. A separate, freshly initialized app-server client could not attach to recover the task. thread/resume returned thread-store conflict: thread ... already has an active writer; a subsequent narrowly targeted turn/interrupt returned thread not found because the new client did not own the running thread. The active writer is the desktop's long-lived app-server process.

    This appears to be an active-turn ownership/control desynchronization rather than only a model-capacity incident. Archiving is not a cancellation mechanism, and the heartbeat/resume path can immediately recreate the running state after unarchive. Restarting the renderer does not clear the persisted active writer/turn state.

    Expected behavior:

    • A capacity failure should leave the preceding turn terminal and the composer usable.
    • If a new turn is accepted, the renderer should attach to it and expose a functional Stop control.
    • Stop should always produce a logged turn/interrupt result: cancelled, already terminal, failed, or unknown.
    • Archive/unarchive and heartbeat resume should reconcile active-turn ownership instead of leaving the task uncontrollable.
    • There should be a supported recovery action for an orphaned active turn that does not require moving the checkout or terminating every running task in the shared app-server.

    Private task content, repository paths, thread/turn IDs, raw logs, and account identifiers are intentionally omitted.

  23. mdotk commented on Sep 17, 2026

    @mdotk

    Follow-up with a deterministic terminal-turn/streaming-state contradiction from the same macOS reproduction.

    After the orphaned turn was successfully interrupted, read-only task APIs consistently reported:

    • thread status: idle
    • latest turn status: interrupted
    • latest turn has a valid completedAt
    • no active backend execution

    However, reopening the task caused Desktop hydration to log this contradictory state:

    latestTurnStatus=interrupted markedStreaming=true
    

    The composer consequently continued showing a spinner and disabled Send even though the backend was idle.

    A simple navigation away/back did not clear it. A deeper remount also reproduced it:

    1. Navigate away from the task.
    2. Archive the idle task.
    3. Unarchive it while still off-screen.
    4. Navigate back, forcing resumeState=needs_resume and a new thread/resume.
    5. thread/resume succeeds, but maybe_resume_success again logs latestTurnStatus=interrupted markedStreaming=true.

    This rules out an active model request and ordinary renderer-route caching. The poisoned streaming marker is persisted or reconstructed during resume despite the authoritative terminal turn state.

    Required invariant: if the latest turn is completed, failed, or interrupted, resume must not return or derive markedStreaming=true. Hydration should reconcile terminal turn status before disabling the composer. A supported per-thread state-repair action is also needed; restarting the shared app-server would disrupt unrelated active tasks.

  24. mdotk commented on Sep 17, 2026

    @mdotk

    Further reproduction: the invalid streaming state propagates through thread/fork and can become worse in the child.

    Sanitized sequence:

    1. Source task latest turn was authoritatively terminal:
      • status=interrupted
      • valid completedAt
      • task backend idle
    2. User forked the task through Desktop.
    3. The first child later had another interrupted turn. In that child, the turn eventually received a completion timestamp after archival.
    4. User forked that child while its latest turn was interrupted.
    5. The second child copied the latest turn as:
      • status=interrupted
      • completedAt=null
      • durationMs=null
    6. Read-only task APIs report the second child as idle, but initial hydration logs:
    latestTurnStatus=interrupted markedStreaming=true
    
    1. Desktop consequently shows Thinking, disables Send, and leaves the draft greyed out. No model request or tool call is active.

    The fork call itself succeeded; the problem is the lifecycle state copied into the child. Forking again repeats the failure because the child inherits an interrupted turn without a completed timestamp and then reconstructs it as streaming.

    Required invariants:

    • thread/fork must only copy completed history, as documented by the product behavior, and must normalize interrupted turns to a terminal record with completedAt.
    • A fork must never hydrate with markedStreaming=true unless it owns a genuinely active turn.
    • If imported history contains status=interrupted with no completion timestamp, resume should repair it rather than treating it as streaming.
    • Desktop should prevent or warn about forking an active/detached turn if it cannot produce a terminal snapshot.

    Private task content, paths, thread/turn IDs, and raw logs are omitted.

  25. RohinJ444 commented on Sep 19, 2026

    @RohinJ444

    I saw a similar failure on macOS 26.6.2 (25G83), Apple Silicon, in the desktop app:

    1. During a local coding task, the UI continued showing a shell command as running for approximately an hour.
    2. I opened a side chat to ask about it. That chat reported that the command had already finished, while the main task still appeared to be running.
    3. Clicking Stop produced “Failed to stop chat.”
    4. I also could not steer the task: attempting to send a steering message caused a brief UI flash but did not visibly take effect.
    5. I quit and restarted the app. The task then showed “Worked for 16m.” The code changes and completed test logs were available afterward.

    The main problem was not just the elapsed-time display: I could neither stop nor redirect the task through the UI, and could not tell whether it was actually still executing.

    The roughly one-hour wait and “Worked for 16m” are observations, not measurements of the underlying shell process. I have not established whether steering reached the backend or whether this shares the same root cause as the original report. I do not have a deterministic reproduction yet.

    Potentially separate: the side chat was no longer visible after restarting. Linking #40262 for that symptom rather than assuming it is caused by the same failure.

  26. kalexander-alt commented on Oct 21, 2026

    @kalexander-alt

    Additional macOS reproduction — 21 October 2026

    Codex desktop 26.1016.51333, build 21161, bundle com.openai.codex; macOS 26.6.2, Apple Silicon. This adds measured execution evidence and specific active-turn mismatch observations to the existing issue.

    User-visible problem: the user reported hours without new chat updates, indefinite “Thinking”, and inability to send messages in a long-running local chat. Backend metadata and independently verified document saves show that work continued, with real interruptions as well. Reopening the chat restored a visible update, confirmed by the user. Ongoing reliable message sending has not been independently verified.

    Bounded audit: 21 October 2026, 14:00:00–18:18:02 Europe/Zurich (UTC+02:00) / 12:00:00–16:18:02 UTC.

    • Main turn present: 4h 02m 47.796s; this is not a measure of productive inference time.
    • Main turn absent between turns: 15m 14.204s; background jobs may continue during those gaps.
    • Seven terminal stream failures in this bounded window; gaps after those failures totaled 15m 10.054s. The whole runtime of a subsequently failed turn is not downtime.
    • Saved-file hashes and authoring receipts verify actual new outputs at approximately 15:31–15:35, 16:32, 16:43, 17:25 and 18:11:19 Zurich. This was not a continuous hours-long halt.

    Native request evidence:

    Zurich (UTC+02:00) UTC Observation
    17:33:01.544 15:33:01.544 turn/steer rejected with active_turn_mismatch; expected active-turn ID differed from actual. Successful same-method routing followed 113 ms later.
    18:06:26.495 16:06:26.495 turn/interrupt rejected with active_turn_mismatch; successful same-method routing followed 15 ms later.

    The actual turn identifiers are omitted. Successful request routing does not prove a user message was delivered, applied or displayed. A brief app-global executor restart and window-level pubsub reconnects were observed separately; neither is scoped sufficiently to count as this chat's downtime or explain the stale display.

    The precise display-freeze onset, duration and root cause remain unknown. The chat was active after recovery, and its larger task remains unfinished. Please investigate reconciliation of renderer-visible active-turn state, progress subscriptions and steering targets against the backend. No deterministic repro or fix is claimed.

    No project names, local paths, account details, source files or raw transcripts are included.

    Report reference: macos-desktop-20261021-stale-ui-audit-v1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingsessionIssues involving session (thread) management, resuming, forking, naming, archiving

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions