Skip to content

Codex Desktop: completed subagents restore as Active after reload #37042

Open

Description

@molamola-git

Version and platform

  • Codex Desktop for Windows x64
  • Store package OpenAI.Codex 26.730.8199.0
  • Installed app.asar SHA-256: acba5f408b7c6c909ffbfdf3c7d3f10660897bfbbb10f916a78505986b44b772

Bug

After Desktop reloads a task with a long subagent history, completed child agents are restored under Active instead of Done.

This is not a small count drift. In one reproducible parent task:

Evidence Count
Direct child spawn edges 126
Child rollout ends in task_complete 117
Child rollout ends in turn_aborted 6
Nonterminal or unresolved 3
Desktop panel shows Active 109
Desktop panel shows Done 17

At least 100 durably completed children are therefore displayed as active.

The underlying child records are not lost. A direct thread/read for an affected child returns thread.status = notLoaded and a latest turn whose status is completed.

Reproduction

  1. Open a Desktop task.
  2. Spawn and complete enough subagents for the parent to retain several historical children.
  3. Restart Desktop or otherwise cold-hydrate that task.
  4. Open the Subagents panel.
  5. Observe completed children under Active.
  6. Directly read one of those children: the runtime thread status is notLoaded, while its latest durable turn is completed.

Root cause

The shipped renderer's descendant discovery uses:

thread/list
ancestorThreadId=<parent>
sourceKinds=["subAgentThreadSpawn"]
useStateDbOnly=true

Stored children that are not loaded in the current app-server process correctly arrive with runtime ThreadStatus.notLoaded. The renderer then combines that with the parent's historical subAgentActivity state. Parent activity has started, interacted, and interrupted, but no durable completed activity kind. As a result, the stale parent-side running reference wins and the child is projected as Active.

The renderer already has a correct latest-turn fallback for descendants that were observed but missing from thread/list: it reads turn history and maps terminal latest turns away from Active. That fallback is not applied to descendants that were successfully returned by the state-DB list, which is exactly the cold-reload case above.

thread_spawn_edges.status = open is not a runtime status and should not be changed or interpreted as Active/Done.

Minimal safe fix

During descendant discovery, hydrate only listed children whose runtime status is notLoaded:

thread/turns/list
threadId=<child>
cursor=null
limit=1
sortDirection=desc
itemsView=notLoaded

Projection:

  • latest completed -> Done
  • latest failed or interrupted -> existing failure/interruption policy; never Active
  • latest inProgress returned by the current app-server -> Active; the server normalizes stale non-running inProgress turns to interrupted, so this represents the list-to-live race
  • no turn/read failure -> remain unknown and stay out of Active; do not guess Done
  • already loaded runtime active, idle, or systemError records are not queried or overwritten
  • live thread/status/changed=active evidence wins over the hydrated historical snapshot

To keep the large-history path bounded:

  • use one class-wide semaphore to cap concurrent latest-turn reads (a local patch uses 8),
  • deduplicate only simultaneous in-flight reads for the same (threadId, updatedAt),
  • remove settled results so second-resolution updatedAt cannot make same-second lifecycle changes stale and the cache cannot grow without bound,
  • return only one latest turn over the wire,
  • do not repurpose spawn-edge status.

Performance caveat: in the current legacy app-server path, thread/turns/list limit=1 still reconstructs the child's full rollout internally before truncating the response. A renderer-only correction therefore performs up to one full replay per cold notLoaded child and can repeat that work on later discovery cycles. The production fix should expose an indexed latest lifecycle projection in descendant listing or use indexed turn metadata; the renderer candidate must not be presented as performance-proven on a 126-child live history until that cost is measured.

Regression coverage requested

  1. Cold restart: parent has only started/interacted; child runtime is notLoaded; latest turn is completed -> Done 1, Active 0.
  2. A list-to-live race returns latest inProgress from the current app-server -> Active 1, Done 0.
  3. Latest turn is interrupted or failed -> not Active; keep the terminal turn available to the existing UI policy.
  4. Missing/corrupt history -> unknown, not guessed Done.
  5. A same-second empty/interrupted read followed by completed is reread and projected Done.
  6. Simultaneous reads for the same generation are deduplicated, but a later discovery rereads it.
  7. Loaded runtime active, idle, and systemError are never queried or overwritten.
  8. Two simultaneous large discovery calls share a global concurrency cap of 8.
  9. Mixed 126-child fixture -> Done 117, Active 2, interrupted excluded 6, unknown excluded 1.
  10. Real legacy 126-child hydration -> measure wall time, peak memory, and renderer responsiveness, or use an indexed backend projection that avoids full rollout replay.

A byte-guarded local renderer patch passes a regression that executes the exact injected production hydration methods, the shipped HFs projection, and the shipped side-panel Done/Active predicates. The 126-child fixture produces Done 117 and Active 2; six interrupted and one unknown child stay out of Active. The signed Store package was not modified.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    subagentIssues involving subagents or multi-agent features
    windows-osIssues related to Codex on Windows systems
    on Aug 5, 2026
  2. github-actions commented on Aug 5, 2026

    @github-actions
    Contributor

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

    Powered by Codex Action

  3. BoddhaBuddha commented on Aug 5, 2026

    @BoddhaBuddha

    Confirmed on macOS. After restarting or reloading a task, 223 completed historical subagents remain displayed as Active despite no live workers. The affected child threads return notLoaded, while their latest durable turns are completed, matching the diagnosis in this issue.

  4. HiveTender commented on Aug 8, 2026

    @HiveTender

    I’m experiencing the same issue on Codex for Windows 26.803.5235.0.

    Historical subagents can be moved from Working to Done by opening each one, but after fully quitting and relaunching Codex, the panel reconstructs the same incorrect state: 14 Working and 2 Done. The 14 displayed runtimes then continue increasing.

    This persists after setting:

    [agents]
    enabled = false

    The setting is loaded successfully and no multi-agent tools are available, so this appears to be a persisted-status/UI reconciliation problem rather than active agent execution.

    Feedback ID: 019fd8ce-77e5-7cd0-8303-bb92cc9ed4ed

  5. disbitski commented on Aug 8, 2026

    @disbitski

    Confirmed on macOS 26.6.1 arm64 with Codex Desktop 26.803.41515 (build 6321).

    A long-running task displayed 112 historical subagents under Active / Working, including entries with elapsed times exceeding three days. An authoritative agent-tree check showed only the parent task running; the recent child audits were completed. Attempting to interrupt one displayed historical child returned not_found.

    A read-only process check also found the normal Codex application processes—not 112 active workers—and account utilization remained stable. This supports the issue’s diagnosis that completed historical children are being reconstructed as Active rather than actually executing.

    No project names, repository paths, prompts, thread IDs, account information, or screenshots are included because the local labels contain private project context.

  6. timsoret commented on Aug 13, 2026

    @timsoret

    Independent reproduction on Codex Desktop for Windows, observed 2026-08-13.

    In a long-running parent task with many historical delegation waves, the Subagents panel showed:

    • 82 working
    • 18 done

    At the same time, an authoritative runtime status query returned the parent as the only running agent and every listed child as completed. The completed children had already returned final results; no child work remained active.

    This makes the Working counter entirely non-authoritative for the affected task and strongly matches the stale/cold-hydrated lifecycle projection described here. The practical impact is that users cannot tell whether background work or concurrency slots are genuinely active.

    A cropped screenshot showing only the Subagents counters was captured; it contains no project or conversation data.

  7. ADABman commented on Aug 13, 2026

    @ADABman

    Additional reproduction on Arch Linux, observed 2026-08-13.

    This is the unofficial AUR repackaging of the Codex Desktop bundle, so I am including the exact versions:

    • Desktop package: openai-codex-desktop 26.803.81509-8
    • Bundled core: codex-cli 0.147.0-alpha.6.6

    In a long-running parent task, the Subagents panel showed 209 Active / Working and 41 Done after a full host reboot.

    A sampled child still displayed as Working had authoritative state thread.status = notLoaded and latest turn.status = completed; its turn had completed roughly 11 hours earlier. The machine had rebooted after that completion, so it could not be a surviving worker process. A read-only process-tree check showed the normal Desktop app-server/renderer processes, not a corresponding population of live workers.

    The parent had 231 direct persisted spawn edges whose edge status was open. I am reporting that only as persistence-shape evidence; consistent with this issue, I did not interpret or modify spawn-edge status as runtime state.

    Restart/reboot did not reconcile the panel. This appears to confirm the same cold-hydration/status-projection mismatch on Linux and on the newer bundled core.

    No task names, repository paths, prompts, thread IDs, account data, or screenshots are included.

  8. Sythos commented on Aug 14, 2026

    @Sythos

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

    #37041

  9. derongliang commented on Aug 16, 2026

    @derongliang

    Additional Windows reproduction, observed 2026-08-16, confirms that this issue still persists in the newer Desktop build.

    • Platform: Windows x64
    • Microsoft Store package: OpenAI.Codex 26.810.7004.0
    • A long-lived parent task shows 115 Running and 7 Done in the Subagents panel.
    • A direct read reports the affected parent as idle; its latest parent turn is completed.
    • The parent rollout contains 118 unique subagent thread IDs. Its canonical parent-side activity events contain 118 started, 182 interacted, 10 interrupted, and no completed activity kind, matching the stale-projection signature described in this issue.
    • Sampled children represented by the historical activity return thread.status = notLoaded with latest turn.status = completed.
    • Fully quitting and relaunching the app does not reconcile the panel; the same 100+ historical children remain under Running.
    • A read-only process check shows only the normal Desktop/app-server/renderer process set, not a corresponding population of live workers.

    This confirms the cold-hydration bug is still reproducible on Windows after the originally reported 26.730 build and remains present in 26.810.7004.0.

    No project names, repository paths, prompts, thread IDs, account data, local state files, or screenshots are included. No cache, database, task, or project data was modified during diagnosis.

  10. zeefine commented on Aug 18, 2026

    @zeefine

    Reproduced on macOS with Codex Desktop 26.810.41047.

    After fully quitting and relaunching Codex, the Subagents panel shows three historical child agents as Running.

    Observed behavior:

    1. The parent task completes normally and receives the final results from all three child agents.
    2. After restarting Codex, the sidebar shows “3 Running”.
    3. Opening the Subagents panel shows all three agents as processing.
    4. Opening their details reveals that they are already completed.
    5. After opening the details, the sidebar updates them to Done.
    6. Fully quitting and relaunching Codex restores the same incorrect Running state again.

    Read-only local evidence:

    • The parent rollout contains three sub_agent_activity entries with kind=started and one kind=interacted, but no completed activity kind.
    • Each child rollout ends with task_complete.
    • A runtime list_agents query reports all three children as completed.
    • The parent rollout also contains the three FINAL_ANSWER inter-agent messages, so the parent correctly received their results.
    • No continued child-agent execution was observed.

    This appears to match the cold-hydration/status-projection issue described here: completed child turns are durable, but the Desktop sidebar reconstructs them as Running after restart.

    Raw rollout files are omitted because they contain private project paths, prompts, and task content.

  11. laizeyu1997 commented on Aug 21, 2026

    @laizeyu1997

    I can reproduce the same user-visible bug on a newer Windows build, and in this case it affects both local tasks and tasks running through Remote SSH.

    User-visible problem

    Several parent tasks in the main Codex sidebar show badges indicating that multiple subagents are still processing.

    However:

    • those parent tasks are no longer using any subagents;
    • all of the displayed child agents have already completed or been interrupted;
    • no affected child has an active execution turn;
    • the live-agent registry contains no corresponding running children;
    • fully quitting and reopening Codex does not clear the indicators.

    This makes the sidebar look as though multiple background agents are still consuming resources, even though no such child execution exists.

    Environment

    • Codex Desktop for Windows: 26.818.3698.0 (x64)
    • Remote Linux app-server/CLI: 0.148.0
    • Affected task backends:
      • local Windows
      • Linux through Remote SSH

    Scope of the affected tasks

    The stale processing state was found on three separate parent tasks:

    • one local Windows parent;
    • two Remote SSH parents.

    Their recorded child relationships contained 48 child threads in total:

    • 6 local children;
    • 42 Remote SSH children.

    Every one of those 48 child threads was queried individually from its actual host.

    Results:

    Child location Count Runtime thread status Latest turn status
    Local Windows 6 6 notLoaded 5 completed, 1 interrupted
    Remote SSH 42 42 notLoaded 41 completed, 1 interrupted
    Total 48 48 notLoaded 46 completed, 2 interrupted

    There were zero children with an active runtime status.

    One parent task itself was still active, but it had no active child agents. The sidebar was therefore conflating parent activity or persisted child history with live subagent execution.

    Persisted-state evidence

    The local and remote Codex state databases were inspected separately.

    Remote state database:

    • 42 rows existed in thread_spawn_edges;
    • all 42 rows had status='open';
    • they matched the same 42 Remote SSH child threads verified above as notLoaded;
    • their latest turns were already terminal.

    Local state database:

    • 67 rows had status='open';
    • 6 belonged to the affected visible local parent and matched the six individually verified notLoaded children;
    • the other 61 pointed to already archived historical child threads.

    Therefore, the persisted spawn-edge state disagreed with both the latest child-turn state and the live-agent registry.

    Why restarting does not fix it

    The stale open rows survive application shutdown.

    After Codex starts again, the sidebar restores the parent/child relationships from persistent state. The children are either terminal or not loaded, but they are still projected as processing instead of being reconciled against their latest turn status.

    The observed state flow is:

    child finishes or is interrupted
    → latest child turn becomes completed/interrupted
    → child runtime becomes notLoaded
    → no child remains in the live-agent registry
    → persisted spawn edge remains open
    → Desktop restore/sidebar presents the historical child as processing
    → full application restart reloads the same stale indicator
    

    An open spawn edge may be intended to preserve resumability or history. The problem is that open or notLoaded is being presented as active execution without checking the child’s latest turn.

    Expected behavior

    • “Processing,” “Active,” or “Working” should mean that the child currently has an active execution turn.
    • A completed or interrupted latest turn must never be counted as actively processing.
    • notLoaded must not default to Active.
    • On startup or parent-task restoration, Codex should reconcile all descendant children in one batch instead of requiring users to open them individually.
    • Resumable or historical children can remain inspectable, but they should be displayed separately from actually running agents.
    • A parent task that is active without active children must not inherit a false active-subagent count.

    This provides current-version Windows plus Remote SSH evidence for the same state-reconciliation mechanism described in this issue, and also appears related to #37916, #37876, and #33700.

  12. privacyguy123 commented on Aug 22, 2026

    @privacyguy123

    I've seen this problem since ChatGPT/Codex app merge inception on Windows.

  13. Sythos commented on Aug 22, 2026

    @Sythos

    I've seen this problem since ChatGPT/Codex app merge inception on Windows.

    not just windows, seen also on macosx and on last linux gui app too, the source is sort of deeper than the platform UI

  14. pomazanbohdan commented on Aug 23, 2026

    @pomazanbohdan

    Cross-case Windows evidence: after child rollouts reached task_complete and no child remained in the live registry, reopening the parent projected the same children as Active/Working again. Historical parent activity plus notLoaded child state matches the projection gap here and connects the UI symptom to #38364, #37916, and the capacity failure in #39694.

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

    Papercuts 2026appIssues related to the Codex desktop appbugSomething isn't workingsubagentIssues involving subagents or multi-agent featureswindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions