Codex Desktop forked thread can also become zombie active/inProgress with only user message
What version of Codex are you using?
Codex Desktop 26.623.101652 / build 4674.
Which platform are you using?
macOS 26.5.1 build 25F80.
What happened?
A Codex Desktop thread became stuck in a zombie active / inProgress state, and a same-worktree fork of that thread reproduced the same failure after a simple follow-up message.
This is related to #28499, but I am opening this as a separate concrete case because the fork did not recover the thread and instead entered the same zombie state.
Original stuck thread observed through Codex thread inspection:
threadId: 019f2e1e-b18a-7ea3-bfd8-1d2a2d30f2b9
title: 多agent
status: active
latestTurnId: 019f3699-fb1b-75c1-8d48-f0a555de36cb
turnStatus: inProgress
completedAt: null
error: null
items: []
Immediately before this, the user had sent 继续; that turn was interrupted after about 58s. The next in-progress turn then existed with no user-visible assistant output, no tool call, no command output, and no surfaced error.
A forked thread then reproduced the issue:
forkedThreadId: 019f36a0-feb2-7721-a94b-6352b31bcc88
title: 多agent
status: active
latestTurnId: 019f36a1-2808-78b3-880d-f0f152b28a33
turnStatus: inProgress
completedAt: null
error: null
items: [userMessage: "继续"]
The fork copied completed history, but after sending a simple follow-up (继续) it also remained active/inProgress without any assistant response or tool activity.
Steps to reproduce
Exact minimal reproduction is not yet confirmed, but this happened in a real Desktop session:
- Use Codex Desktop on macOS.
- Work in a local git worktree.
- Build up a long-running, image-heavy thread with screenshots/browser artifacts and multiple tool calls.
- Interrupt a long turn.
- Send a follow-up message such as
继续. - Observe the source thread remain
activewith latest turninProgress, no assistant/tool items, and no error. - Fork the thread.
- Send the same simple follow-up in the fork.
- Observe the fork also remain
active/inProgresswith only the user message recorded.
Expected behavior
- The original thread should recover, fail explicitly, or expose a stale/interrupted state.
- A forked thread should provide a clean recovery path from completed history.
- If the worker fails to start or the stream/session state is invalid, the turn should transition to a visible failed/stale/interrupted state rather than staying active forever.
- The UI or thread inspector should expose worker liveness / last heartbeat so users can distinguish real running work from a zombie turn.
Actual behavior
- Original thread stayed
activewith an empty in-progress turn. - Forked thread also stayed
active/inProgressafter a simple follow-up. - The forked latest turn contained only the user message.
- No assistant message, tool call, command output, or error was surfaced.
Additional context
- The source thread was long-running and image-heavy, with browser screenshots/generated image outputs in history.
- The source thread had multiple interrupted turns before the stuck active turn.
- The underlying project was not blocked at the build level: a separate shell check of the same worktree showed
npm run buildcompleted successfully. - Some project tests were failing due to ordinary unfinished work, but the Desktop issue happened before any assistant/tool execution in the latest turn, so this appears to be a Desktop/session lifecycle issue rather than a project command hang.
Related issue
- #28499