Missing rollout leaves an unarchivable ghost thread in the Windows sidebar
Bug: Missing rollout leaves an unarchivable “ghost” thread in the Windows sidebar
Summary
On the Codex/ChatGPT Windows desktop app, a local thread remained visible in the sidebar and repeatedly failed to archive because its rollout file was missing while the state database still retained the thread row and stale rollout path. The item survived full app restarts and was also treated as a pinned thread by the renderer even after the backend could no longer load it.
The UI eventually reported archive success only after the stale local state was cleaned up and an explicit unpin operation was sent. The app should self-heal this state without requiring manual SQLite/session cleanup.
Environment
- Platform: Windows 10 Home China 22H2, build 19045.6466, x64
- Desktop app release reported in logs:
26.814.41957 - App server version:
0.148.0-alpha.15 - Selected Codex runtime bundle:
26.819.11345 - Date observed: 2026-08-20
- Thread title:
11 - Thread ID:
01a01437-8518-78d2-8485-d0512fcbc1c5 - Deep link:
codex://threads/01a01437-8518-78d2-8485-d0512fcbc1c5
Preconditions inferred from logs and local state
state_5.sqliteretained a row for the thread.- Its
rollout_pathpointed to a JSONL file that no longer existed. - The renderer/sidebar still retained the thread in its pinned/recent state.
The stale path was equivalent to:
%USERPROFILE%\.codex\sessions\2026\08\18\rollout-...-01a01437-8518-78d2-8485-d0512fcbc1c5.jsonl
Steps to reproduce
The original cause of the missing rollout is unknown, but the broken state can be described as follows:
- Have a local thread row in
state_5.sqlitewhoserollout_pathno longer exists. - Keep that thread visible or pinned in the sidebar.
- Restart the desktop app.
- Try Archive from the thread overflow menu, sidebar context menu, or Recent tasks menu.
Actual behavior
- The app repeatedly shows archive failure.
- Restarting does not remove the sidebar item.
- The stale thread can remain visible even though
thread/readandturn/startreport that the thread is missing/not loaded. - Archive may fail through two related paths:
- internal OS error because the rollout file is missing;
no rollout found, followed by failure to persist the inactive-thread archive.- The renderer can continue trying to hydrate the item as a pinned thread.
Expected behavior
If a thread's rollout is missing but a state-database/sidebar record remains, Archive should still remove the item from active and pinned sidebar state. The app should transactionally reconcile or quarantine the stale database row, clear its pinned state, invalidate the renderer cache, and optionally surface a recoverability warning. It should not require the missing rollout file merely to hide/archive the sidebar entry.
Sanitized log evidence
Archive requested ... method=thread/archive
errorCode=-32603
failed to archive session: thread-store internal error: failed to archive thread:
The system cannot find the file specified. (os error 2)
Archive skipped because thread has no active rollout
errorMessage="no rollout found for thread id 01a01437-8518-78d2-8485-d0512fcbc1c5"
Failed to persist inactive thread archive
errorMessage="Inactive thread archive did not persist"
state db list_threads returned stale rollout path for thread
01a01437-8518-78d2-8485-d0512fcbc1c5
state db discrepancy during list_threads_db: stale_db_path_retained
thread/read ... errorCode=-32600
message="thread not loaded: 01a01437-8518-78d2-8485-d0512fcbc1c5"
Failed to read pinned thread
threadId=01a01437-8518-78d2-8485-d0512fcbc1c5
Recovery that ultimately worked
The user observed successful archiving only after all of the following stale state had been reconciled:
- removed the stale thread row and exact-ID references from local structured state;
- confirmed the missing rollout/session file had no remaining live index entry;
- explicitly set the thread's pinned state to false;
- retried Archive in the desktop app.
Suggested fix
When thread/archive encounters rollout_not_found or OS error 2:
- fall back to a state-database-only archive transaction;
- clear
is_pinnedand any renderer-side pinned ID for the thread; - invalidate the sidebar query/cache;
- remove or quarantine stale
rollout_pathentries; - return success if the thread is no longer present in active sidebar state.
This would prevent a permanently visible “ghost” thread and avoid requiring users to edit local databases manually.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional reproduction from the same day, with a different failure variant:
Environment
OpenAI.Codex 26.818.2441.00.148.0-alpha.21Important difference
For this affected thread, the rollout JSONL file exists and is readable. The thread is also present in
session_index.jsonl, andcodex doctor --summaryreports that the state database is healthy and the rollout/thread inventories agree.Despite that, all archive paths fail:
The CLI reports:
Recovery attempts
codex migrate-rollouts --thread <redacted-thread-id> --json --verboseeligible--apply.migratedAfter migration, the task became readable/idle, but Archive still fails with OS error 2. No conversations were deleted; backups were made before migration.
A second completed task also intermittently appears as
notLoadedafter restart. This may indicate that the archive path resolver is using a stale or differently normalized rollout path even when the file and catalog entry both exist.Please consider handling
rollout_not_found/OS error 2 by reconciling the state DB, session index, and resolved rollout path before failing the archive operation. I can provide a focused sanitized log excerpt and screenshot if needed.