Codex Desktop repeatedly resumes stale rollout after Stop → Edit → Send (thread/revert)
What version of the Codex App are you using (From “About Codex” dialog)?
Codex Desktop 26.820.60940 (build 7119), with bundled codex-cli 0.150.0-alpha.8.
What subscription do you have?
Not relevant to the failure. It occurs in the local Desktop/app-server task lifecycle before a model request.
What platform is your computer?
Darwin 25.5.0 arm64 arm
What issue are you seeing?
After Stop → edit an earlier user message → Send, Codex Desktop reverts the task's history. The task keeps the same stable thread ID, but its active local rollout JSONL file changes.
If the same task was already open in another top-level Desktop window, that window can retain the original rollout path. Reselecting the task there shows a blank task/plan and repeatedly raises:
Failed to resume chat
cannot resume running thread <thread-id> with stale path:
requested `<original rollout>.jsonl`,
active `<replacement rollout>.jsonl`
The two paths are different valid history files for the same stable thread ID, not alternate spellings of one path.
The window roles are:
- Source window: the window where the user stops the running turn, edits an earlier message, and sends it.
- Stale window: another window that had already loaded the same task before the edit.
Source window Stale window
(same task already loaded) (same task, pre-revert state)
│ │
│ Stop → Edit earlier message → Send │
▼ │
thread/revert │
│ │
├─ stable thread ID retained │
└─ replacement rollout selected │
│
└─ reselect task
│
└─ resume sends original rollout
│
▼
blank task + repeating toast
Local process correlation ties the affected task to the app-server bundled in the standard macOS /Applications/ChatGPT.app. It was not handled by a standalone CLI, IDE extension, Claude process, or separately profiled AI Fleet app. Rollout metadata reports originator: "Codex Desktop" and cli_version: "0.150.0-alpha.8"; app-server telemetry reports client Codex Desktop version 26.820.60940 over stdio.
What steps can reproduce the bug?
- Start Codex Desktop and open an existing local task.
- Open that same task in two distinct top-level Desktop windows. Use Open in New Window if necessary.
- Wait until the task's history is visible in both windows, and keep both open.
- In the source window, submit a message and wait until the turn is running.
- Click Stop.
- Choose Edit on an earlier submitted user message, change it, and click Send.
- Switch to the stale window. Select another task and then reselect the affected task so Desktop attempts to resume it.
- Observe the blank task/plan and repeating Failed to resume chat toast. The toast identifies the pre-edit rollout as
requestedand the replacement rollout asactive.
The complete failure was observed on the reported task. A separate task independently confirmed the trigger—Stop → edit an earlier message → Send produced a native rpc.method="thread/revert" request—but was not a second independent reproduction of the stale-window toast loop.
What is the expected behavior?
- Every open window showing a task should converge on the active post-revert history.
- A stale window should recover by the stable thread ID and display the active history.
- A retired rollout path should not displace or block the already-loaded logical thread.
- Desktop should not retry the same failed resume indefinitely or produce an unbounded toast loop.
Additional information
Ready implementation PR on a public fork
The implementation is a numbered, reviewable PR at joshmouch/codex#1, rebased onto current upstream main. The current implementation commit is 8549ea49af, and the upstream comparison is ready for an upstream collaborator to open directly against openai/codex.
Suggested repair
The server-side rule should have one owner: when threadId resolves a thread already loaded by app-server, that stable identity is authoritative. path is a mutable rollout locator and should not become a second selector after the live thread has already been found. The PR therefore ignores path in the loaded-thread branch and returns the active rollout path.
The cold-resume boundary remains strict. For an unloaded paginated thread, a supplied path must be current; a stale path is rejected and the client can omit it to resume by stable thread ID. This matches the current upstream behavior added in 0d654e6536.
Desktop should still treat thread/reverted as cross-window cache invalidation, omit experimental thread/resume.path from ordinary ID reattachment, and bound identical failed retries/toasts. Those are defense-in-depth around the unambiguous server rule.
The complete task/thread ID, rollout paths, screenshot, and sanitized local log extracts can be supplied privately if maintainers need them.
This is not the archive/unarchive stale-state case, the Windows \\?\\ path-canonicalization case, or the app://-/index.html new-window bundle-load failure. It occurs on macOS after an explicit history edit and involves two distinct rollout files for one stable thread ID.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
This is related to, but not a duplicate of, #40609.
thread/revert. A second, already-hydrated Desktop window then sends the retired rollout path together with the still-running thread ID, receivescannot resume running thread ... with stale path, becomes blank, and loops error toasts.The updated implementation PR on the public fork fixes #40955 by making the loaded
threadIdauthoritative and ignoringpathonly after that stable ID has resolved the live thread. It preserves current-path enforcement for unloaded paginated threads. It does not rebuild #40609's missing UI projection or explain why that issue performs an unexpected implicit revert. Closing either report as a duplicate would lose a distinct trigger, failure surface, root cause, and acceptance test.