Codex Desktop macOS: unarchive updates local state, then returns `failed to read unarchived thread`; thread appears after restart
Summary
On the macOS desktop app, Settings → Archived chats → Unarchive intermittently shows a red failure toast and returns JSON-RPC error -32603:
failed to unarchive session: thread-store internal error:
failed to read unarchived thread <codex_home>/sessions/YYYY/MM/DD/rollout-<redacted-thread-id>.jsonl
However, the storage mutation has often already succeeded:
- the rollout has moved from
archived_sessions/tosessions/YYYY/MM/DD/; state_5.sqlite.threads.archivedis already0;rollout_pathalready points to the active sessions path;- after fully quitting and reopening the app, the thread appears in the left sidebar and works normally.
This is therefore a false-negative unarchive result plus a stale Desktop UI, rather than data loss.
Environment
- Desktop app display name: ChatGPT
- Bundle identifier:
com.openai.codex - Desktop version:
26.715.21425 - Bundle build:
5488 - Bundled CLI:
codex-cli 0.145.0-alpha.18 - Platform: macOS
26.5.2, Darwin25.5.0 arm64 - Observed: 2026-07-17
Frequency and local evidence
In one day of desktop logs:
- 4 failed
thread/unarchivecalls across 3 distinct local threads; - 3 successful
thread/unarchivecalls in the same period; - one affected thread produced the same failure twice;
- failed calls returned in roughly 18–52 ms, with no preceding network timeout.
Sanitized sequence:
T+0ms Unarchive requested conversationId=<redacted>
T+18ms method=thread/unarchive errorCode=-32603
T+51ms Request failed:
failed to unarchive session: thread-store internal error:
failed to read unarchived thread <codex_home>/sessions/.../<redacted>.jsonl
Post-failure checks:
state_5.sqlite integrity_check: ok
affected rollout JSONL parse checks: all passed
thread row: archived=0
rollout_path: <codex_home>/sessions/YYYY/MM/DD/<redacted>.jsonl
restart Desktop: thread appears in sidebar
No raw logs, thread IDs, task titles, prompts, account data, or real local paths are included here.
Size correlation
The three failed unarchive attempts involved rollout files of approximately:
- 18.8 MB
- 24.4 MB
- 31.5 MB
Three successful attempts in the same period involved rollout files of approximately:
- 2.5 MB
- 2.8 MB
- 4.0 MB
All six were ordinary readable JSONL files. This suggests that long/large histories may make the final summary-read path more likely to fail, but this evidence does not establish a fixed byte threshold.
Suspected cause
The current unarchive implementation appears to:
- rename the rollout into
sessions/YYYY/MM/DD/; - mark the state DB row unarchived;
- call
read_thread_item_from_rollout(...); - return an internal error if that final read yields
None.
There is no rollback after steps 1–2. Therefore a failure at step 3 can return an error even though the unarchive mutation is already committed. The Desktop UI then remains stale until restart.
It would also help if the error preserved the underlying reason why read_thread_item_from_rollout returned no item, rather than collapsing it to the generic failed to read unarchived thread message.
Steps to reproduce
The failure is intermittent and appears more common with long local threads:
- Create/use a sufficiently long local Desktop thread.
- Archive it.
- Open Settings → Archived chats.
- Click Unarchive.
- Observe a red failure toast containing
failed to read unarchived thread. - Fully quit and reopen the desktop app.
- Observe that the thread is now present in the active left sidebar.
Expected behavior
- A successfully moved and DB-updated thread should produce a successful unarchive response.
- The active and archived lists should refresh immediately.
- If summary hydration fails after the mutation, the app should either:
- return success and refresh using persisted DB metadata; or
- roll back the mutation atomically and report the underlying parse/read reason.
- Repeated clicks should not be required.
Actual behavior
- The API reports unarchive failure.
- The UI shows a red failure toast and does not immediately show the thread.
- The underlying thread is often already unarchived.
- Restarting the app makes it appear in the left sidebar.
Related issues, but not exact duplicates
- #11907 reports that restored conversations may not refresh until restart, but does not include the
-32603 failed to read unarchived threadfalse-negative after the local mutation already succeeded. - #20317 concerns a persistent sessions/archived_sessions path mismatch that restart does not fix.
- #27202 concerns missing
hostIdand archived-list discoverability.
This report adds the exact app-server error, storage/DB post-state, restart behavior, same-day success/failure comparison, and rollout-size correlation.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗