Codex desktop rehydrates closed, terminal subagents as Working after restart

Open 💬 15 comments Opened Aug 8, 2026 by palmer-Eormen
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Codex desktop 26.803.41515 (build 6321, Chromium 151.0.7922.76) incorrectly rehydrates completed and aborted subagents as Working after application startup.

The affected sessions are not live. Every inspected child rollout has a terminal event, every persisted spawn edge is closed, and backend lookup returns not_found. The Subagents panel nevertheless reconstructs historical children as active, including elapsed times of several days.

Impact

  • False active-agent counts across affected parent conversations.
  • Users cannot determine whether background work actually exists.
  • Completed agents appear to be running for days.
  • The panel may introduce UI/session-loading overhead when many historical children are reconstructed.

Evidence

  • Historical child sessions inspected: 516
  • Parent conversations affected: 11
  • Terminal rollout events:
  • task_complete: 469
  • turn_aborted: 47
  • Missing terminal events: 0
  • Persisted thread_spawn_edges state:
  • closed: 516
  • open: 0
  • SQLite integrity check: ok
  • Backend lookup of affected historical agents: not_found
  • One affected conversation (“Oanda”): 76 recorded subagents; all 76 end with task_complete; the UI still shows them as working.

Reproduction

  1. Use a conversation that previously spawned many subagents and let them complete or abort.
  2. Open the Subagents panel. Completed children may be shown as Working, with long elapsed times.
  3. Quit and restart Codex desktop.
  4. Reopen the same conversation.
  5. The same terminal historical children are rehydrated as active.
  6. Compare persisted edge state:
sqlite3 ~/.codex/state_5.sqlite \
  "SELECT status, COUNT(*) FROM thread_spawn_edges GROUP BY status;"

Expected result for the affected data: all records are closed. The UI still reports the agents as working.

Expected behaviour

On rehydration, the Subagents panel should honour terminal child rollout events (task_complete / turn_aborted) and the persisted thread_spawn_edges.status = closed state. Historical child-session existence alone must not imply a live working agent.

Actual behaviour

The desktop UI appears to infer Working from a historical subagent session or spawn record, ignoring terminal and closed state.

Additional observation

Resuming one representative stale child and explicitly closing it produced a shutdown notification. This suggests the live UI understands an explicit shutdown transition but fails to recognise already-terminal historical sessions during startup.

Scope and safety

This report is diagnostic only. No project files, databases, caches, conversations, or project artefacts were changed during investigation.

View original on GitHub ↗

15 Comments

github-actions[bot] contributor · 20 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #37041
  • #37042
  • #37222
  • #37426
  • #37299

Powered by Codex Action

psychicEgg · 20 days ago

Confirming the subagent respawn bug in ChatGPT/Codex for Windows app Version 26.803.41515

<img width="827" height="599" alt="Image" src="https://github.com/user-attachments/assets/d6e4adfa-0cf7-4d49-a2f5-8f7857a19204" />

The live collaboration registry contains no active child agents, and direct termination attempts for all seven return not_found.
The rows remain visible after navigating away from and back to the task.

CapyKkuing · 19 days ago

I can reproduce this issue on Windows with Codex desktop 26.803.5235.0. I also submitted in-app feedback ID 019fe03e-8971-7df3-afe2-4ce8e6675f8c.

Additional behavior that may help isolate the refresh path:

  • Fully quitting and restarting Codex does not clear the stale Working state.
  • Opening an affected child (whose final output is already present) and then pressing Back immediately changes its status to Completed. This looks like child-view navigation forces a status refresh.
  • One completed subagent remained displayed as Working for 25 days.

Without attaching private logs or local paths, desktop logs between 2026-08-01 and 2026-08-08 repeatedly recorded Received turn/completed for unknown conversation (44 occurrences) and Received turn/started for unknown conversation (86 occurrences). One inspected target was identified by the app as an ephemeral thread. No data loss was observed.

indyfromoz · 19 days ago

Confirming this on macOS with Codex Desktop 26.803.41515 (build 6321), macOS 26.5.2 (25F84).

Additional reproduction evidence from an affected task:

  • The Subagents panel showed 12 entries as Active / Working although the child work had finished.
  • After fully quitting and restarting Codex, the stale count dropped to 5, but those five still appeared as Active / Working.
  • The collaboration lifecycle registry reported those exact five children as completed; only the root task was running.
  • Direct interrupt attempts against older stale rows returned not_found.

The partial drop from 12 to 5 after restart suggests startup performs some reconciliation but does not consistently apply the authoritative terminal state to every restored row.

This evidence establishes a presentation / rehydration mismatch. It does not establish that the stale rows consume tokens or retain live processes.

Expected: startup should reconcile every restored child against authoritative lifecycle state and show only live children under Active / Working.

Basilisk-bat · 19 days ago

Additional reproducible evidence from Codex Desktop 26.803.5235.0 on Windows:

  • The UI showed 127 working + 39 done = 166.
  • The parent had exactly 166 unique direct child spawn-edge records at that moment; every edge was still persisted as open.
  • Reading the terminal event from each child rollout produced 159 task_complete and 7 turn_aborted; 0 were running.
  • The live collaboration registry independently reported no active child agents at the screenshot boundary.

The packaged renderer explains the exact inflation. The collapsed summary computes:

working = agents.filter(status !== "done")
done    = agents.filter(status === "done")

The upstream view model exposes active, waiting, and done. When historical children are not hydrated/reconciled, they can fall through to waiting; the renderer then labels those waiting records as working. This is why the two visible counts still add up exactly to the historical child count even though none is live.

A version- and hash-pinned local dry run split the presentation into active/waiting/done/fallback-history and changed exactly the one renderer bundle; 5,751 other packaged files and all 37 native sidecar files remained unchanged. The installed app was not mutated by that diagnostic.

Recommended upstream repair has two parts:

  1. Reconcile/close spawn edges from authoritative terminal rollout events (task_complete, turn_aborted, failure/cancel paths) during lifecycle updates and restore.
  2. In the collapsed summary, count only status === "active" as working. Render waiting separately (or omit it from the working count), and never infer unknown/unhydrated state as working.

A compact regression fixture is: 127 stale waiting records, 39 hydrated done records, and 3 genuinely active records. The collapsed summary must report 3 working, not 130; after lifecycle reconciliation, the 127 terminal records should move to done/aborted rather than remain waiting.

Basilisk-bat · 19 days ago

Correction after tracing the public backend semantics on current openai/codex main: ThreadSpawnEdgeStatus::Open can represent a child that is live or resumable. A normal TurnComplete is therefore not, by itself, authority to close the spawn edge; explicit agent close/interrupt/removal paths must remain distinct.

So please do not implement the earlier lifecycle recommendation as “close every edge on task_complete.” The safe immediate presentation repair remains:

  • count only status === "active" as working;
  • show waiting separately (or exclude it from the working count);
  • never turn unknown/unhydrated history into working;
  • preserve resumable children.

A backend follow-up should reconcile explicit close/interrupt/removal evidence and improve hydration, while retaining the public repo's resumable-agent behavior. The 127 waiting + 39 done + 3 active fixture still applies to the renderer regression: it must report 3 working, not 130.

viggo-lee · 18 days ago

Confirming on macOS with ChatGPT/Codex desktop 26.803.41515 (build 6321) and Codex CLI 0.147.0.

A local state audit found 63 persisted thread_spawn_edges.status = open rows, while authoritative child-thread reads reported:

  • 40 × notLoaded / completed
  • 5 × notLoaded / interrupted
  • 17 × idle / completed
  • 1 × active / inProgress

The UI displayed the historical children as Running across full app restarts.

Calling the supported close_agent path repaired 17 rows, but 45 historical children returned not found and could not be reconciled through the supported API. After the only genuinely active child completed, all remaining stale edges required a backed-up local status-index repair to restore an accurate panel. SQLite integrity remained ok; no conversation or child history was deleted.

In-app feedback was also recorded without private logs: 019fe6aa-1214-7093-a812-0227dd259a13.

This supports the existing renderer concern: unknown/unhydrated or resumable historical children must not be counted or labelled as actively Running. The panel should distinguish Active, Waiting/Resumable, and Done, and startup should safely reconcile explicit close/interruption evidence without treating every terminal child as non-resumable.

antonio-mello-ai · 17 days ago

Confirming the same issue on macOS with ChatGPT/Codex desktop 26.803.41515.

In-app feedback ID: 019fa4ea-4bd3-75a2-b87d-e84aef7c4430

Additional deterministic reproduction evidence:

  1. I manually opened every historical child until the panel showed Active 0 / Done 53.
  2. Switching to another chat and returning preserved Active 0.
  3. I completely quit and relaunched the app.
  4. One minute after the first screenshot, the same task showed Active 52 / Done 1.
  5. No subagent was spawned, resumed, or given follow-up instructions between the screenshots.
  6. The live collaboration registry simultaneously reported no running child agents; only the root conversation was active.

The screenshots below were captured at 08:33 and 08:34, before and immediately after application restart.

<img width="1512" height="982" alt="Image" src="https://github.com/user-attachments/assets/75fafcd8-f8fa-446e-baaa-6108ce02de29" />
<img width="1512" height="982" alt="Image" src="https://github.com/user-attachments/assets/998d912f-3e21-4586-87df-d23c2956be83" />

williamwsmetana-cmd · 17 days ago

Independent Windows reproduction on 2026-08-10. This matches the issue exactly.

Environment and visible behavior

  • Product: Codex Desktop for Windows
  • Affected task: a long-running goal with many historical subagents
  • Subagents panel after restart: 27 Active, with old entries labeled Working for approximately 1–6 days
  • Goal status before cleanup: usageLimited
  • Goal status after pause/termination: blocked / displayed as Goal stalled
  • Reported goal usage: 5,489,555 tokens over 31,573 seconds
  • Full affected thread ID and cropped screenshots are available privately to OpenAI on request.

Recovery attempts that did not work

  1. Paused the goal.
  2. Closed and reopened Codex Desktop.
  3. Signed out and signed back in.
  4. Explicitly changed the goal to blocked/stalled.
  5. Closed and reopened the Subagents panel.
  6. Reopened the affected thread.

The panel still reported 25–27 agents as Active/Working. The count was not stable between refreshes.

Runtime/UI disagreement

The authoritative collaboration runtime reported only the parent agent as running. The three reachable recent children were already completed. Attempts to interrupt several older agents displayed as Working returned not_found, including historical audit/research task names.

This strongly indicates that terminal or nonexistent historical agents are being rehydrated as active UI records. The user cannot determine from the app whether token consumption has actually stopped.

Expected behavior

  • Pausing or blocking a goal should reconcile every child to a terminal state.
  • A child returning not_found must not be displayed as Working.
  • The Active count should be derived from authoritative runtime state, not historical spawn records.
  • The app should expose a task-level “repair/resync subagent state” action.

Account impact and allowance-reset request

This goal exhausted the user’s available Codex allowance while spawning a much larger subagent tree than the user expected. The user is requesting review and restoration/reset of the consumed token allowance associated with this defective run.

I understand GitHub maintainers may not have account-billing tools. Please route this request to the appropriate OpenAI support team or provide a working account-support path for Codex Desktop; in this build, the in-app Help action opens only the Docs agent and does not offer a support-ticket flow.

No project source, secrets, email addresses, or full private thread identifiers are included in this public comment.

restplaced-dev · 16 days ago

Confirming the same stale-subagent rehydration behavior on Windows Codex Desktop.

Additional reproduction pattern from a subagent-heavy workflow:

  1. Let multiple child agents finish normally.
  2. Verify from the orchestration/runtime side that there is no active writer/process for those children and no relevant worktree lock.
  3. Close/reopen the Codex conversation (and in my case, reopening the app/task view also reproduced it).
  4. The Subagents panel rehydrates historical children as Working again even though no child work has resumed.

The important part is that the UI state disagrees with runtime evidence: the panel says Working, while process/lock checks show no active child execution. This can make users think agents are still consuming resources or holding writer slots when they are not.

Expected behavior: on conversation/app rehydration, the Subagents panel should reconcile against authoritative terminal/runtime state and render completed children as Completed (or historical), not Working. UI status should never be used as the sole indicator of active execution when the underlying child is already terminal.

I did not capture the exact Desktop build before leaving the machine, so I am not guessing a version. I can provide a screenshot and exact build later if useful.

restplaced-dev · 16 days ago

Confirming the same restart/rehydration bug on Windows x64.

I am intentionally adding this to the existing issue instead of opening another duplicate because the reproduction matches the reported startup behavior closely.

Reproduction

  1. Run a parent Codex task that spawns several subagents.
  2. Let the child work finish normally and return terminal results.
  3. Verify from runtime/worktree evidence that no child work is actually active (no child-targeting Codex/Flutter/Dart/Git worker process, no relevant lock, and the completed child results are already present).
  4. Close/restart the Codex/ChatGPT desktop app.
  5. Reopen the same parent conversation.
  6. Open the Subagents panel.

Observed

After restart, historical child agents are rehydrated as Working even though no corresponding work has resumed and there is no active writer/process for them.

In the affected workflow, the UI state was therefore materially different from the execution state:

Child work: terminal / no active process
Worktree: no active writer, no relevant lock
Desktop after reopen: Working

No file changes or resumed execution were observed from those stale rows. This looks like a presentation/rehydration-state bug rather than evidence that the old agents are actually running.

Operational impact

This is more than cosmetic for multi-agent workflows:

  • it can make a user wait for work that already finished;
  • it can falsely suggest a shared worktree still has an active writer;
  • it can lead users or orchestration logic to attempt unnecessary close/kill actions;
  • it makes the Subagents panel unsuitable as the authoritative source for agent liveness after restart.

We now have to treat runtime/process terminal evidence as authoritative and mark the panel state as stale when the two disagree.

Expected

On app startup / conversation restore, completed historical children should be reconciled against terminal lifecycle state before rendering. A terminal child may remain visible as history, but it should be shown as Completed/Done, never Working, unless there is a current live execution handle.

If startup cannot confidently reconcile a historical row, a neutral state such as Completed (restored) / Status unavailable would be safer than Working.

Exact Desktop build was not captured during this reproduction, so I am not guessing it. This occurred on Windows on 2026-08-12. No private project names, paths, prompts, thread IDs, or repository data are included in this report.

jazzyalex · 14 days ago

Confirmed on macOS with a smaller but directly comparable reproduction.

Environment

  • Codex Desktop: 26.803.81509 (build 6415)
  • macOS: 15.7.7 (build 24G720)

Observed

  • The Subagents panel showed 24 active agents even though the authoritative live agent registry reported only /root (the current parent task) as running.
  • No live subagents were present in the registry.
  • No local subagent worker processes were present. The remaining Codex-related processes were the normal desktop app/renderer, app-server, browser/computer-use helpers, and tool runtimes.
  • Fully restarting Codex did not reconcile the display; the stale active count increased instead of clearing.

This confirms the UI state can disagree with both the live agent registry and the local process state on macOS. It also makes it hard for users to tell whether model work is still running remotely or whether the display is only stale.

In addition to reconciling the panel against terminal/closed task state on startup, please consider adding a visible Stop all subagents or Dismiss stale subagents action so users can recover from this state without database/cache manipulation.

NgoQuocViet2001 · 14 days ago

Additional quantified Windows reproduction: https://github.com/openai/codex/issues/38364#issuecomment-5289195013

The key result is that 273 Active + 13 Done exactly matched 286 recursively persisted descendants, while all 286 thread_spawn_edges rows remained open. The parent reported only one currently executing child, and the live process tree did not contain hundreds of agent runtimes.

This supports the same root shape reported here: after restart/resume, cumulative persisted spawn history is being rehydrated/classified as live Working state. The fix should reconcile terminal/evicted/interrupted children passively and must not allocate MCP/tool runtime merely to determine their status.

Sythos · 14 days ago

Just asking but, isn't this issue a duplicate of the following?

#37042
#37041
#37426

pomazanbohdan · 5 days ago

Additional Windows evidence confirms the restart boundary: terminal task_complete/turn_aborted children reappear as Working while the live registry has no corresponding child. This bridges #37042's hydration diagnosis and #38364's large-scale panel drift.