Archived session storage should fail fast and support deep archive/cold storage

Open 💬 2 comments Opened Jun 18, 2026 by 100yenadmin

Summary

Codex's archived-session storage contract is brittle for users with very large historical thread stores. If archived rollout files are symlinked to another drive to save local disk, recent Desktop builds can spin or lock up when old/archived threads are listed, read, continued, or unarchived. Even if symlinking internal app storage is not officially supported, Codex should fail fast and avoid app-wide lockups, and it likely needs a first-class "deep archive" / cold-storage workflow for massive long-running thread histories.

Environment

  • Codex Desktop: 26.611.62324
  • Bundle version: 4028
  • macOS app bundle modified: 2026-06-17 22:08 +0700
  • App-server process: /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  • Source checkout inspected: openai/codex main

Local store shape from the affected machine:

  • ~/.codex/archived_sessions is a real directory.
  • It contains 1272 symlinked rollout files pointing to an external drive.
  • It contains 476 regular rollout files.
  • state_5.sqlite contains 1627 archived thread rows and 2929 active thread rows.

Observed behavior

Historically, the user archived massive long-running Codex threads to reduce local disk pressure by moving archived rollout files to a separate drive and symlinking them back into ~/.codex/archived_sessions.

In recent Desktop builds, attempts to continue/message old threads, or otherwise interact with archived thread state, can spin forever and lock the entire app. This started surfacing in the last roughly 48 hours on the affected machine after a Desktop update.

There are two separate concerns:

  1. Symlinks in ~/.codex/archived_sessions are not compatible with the current archive/unarchive implementation.
  2. Even if the symlink layout is unsupported, a bad/slow/missing archived rollout path should not be able to lock the whole Desktop app.

Relevant source pointers

codex-rs/thread-store/src/local/archive_thread.rs:

  • Around archive_thread.rs:30-49, archive resolves a canonical path under ~/.codex/sessions, creates ~/.codex/archived_sessions, then uses std::fs::rename() to move the rollout into the archive directory.
  • Around archive_thread.rs:55-58, the state DB is updated to mark the thread archived at the archived path.

codex-rs/thread-store/src/local/unarchive_thread.rs:

  • Around unarchive_thread.rs:21-40, unarchive locates the archived rollout and validates it with scoped_rollout_path() under ~/.codex/archived_sessions.
  • Around unarchive_thread.rs:56-71, it computes the restored ~/.codex/sessions/YYYY/MM/DD path and uses std::fs::rename() from the canonical archived path back into sessions.

This means symlinked archived files are fragile in two ways:

  • Canonicalization can resolve the file outside ~/.codex/archived_sessions, violating the expected managed-root containment check.
  • rename() can fail across devices or against symlink/cold-storage layouts.

codex-rs/thread-store/src/local/read_thread.rs:

  • Around read_thread.rs:179-199, when include_archived is true, read paths still locate the actual thread path and then fall back to find_archived_thread_path_by_id_str(...).

codex-rs/thread-store/src/local/list_threads.rs:

  • Around list_threads.rs:119-150, archived listing can use a state-DB-only path when requested, but non-DB-only archived listing still reads from the archive collection.

Expected behavior

Codex Desktop should remain responsive even when archived rollout files are symlinks, missing, slow, or otherwise invalid.

At minimum:

  • List/read/resume/unarchive should fail fast for invalid archived rollout paths.
  • A single bad archived entry should be skipped or surfaced as a per-thread error, not cause an app-wide spinner.
  • The UI should distinguish "archived but restorable" from "deep archived / external / unavailable".
  • Docs or diagnostics should warn that ~/.codex/archived_sessions is an app-managed root and should not contain symlinks if Codex is expected to continue/unarchive those threads.

Suggested product direction

Codex likely needs a first-class cold-storage/deep-archive flow for large historical sessions:

  1. "Archive" keeps the thread app-managed and restorable, using real files under Codex's managed archive root.
  2. "Deep archive" or "export" moves/copies rollout files outside the managed root and removes them from normal read/resume/unarchive paths.
  3. The Desktop UI can still show a lightweight manifest row if desired, but it should not treat deep-archived files as immediately continuable.
  4. Restore should copy the file back as a real local file before Codex tries to read or continue it.

That would preserve disk relief for users with very large long-running threads without relying on filesystem symlinks inside an app-owned storage directory.

Reproduction outline

  1. Archive several large Codex threads.
  2. Move the archived rollout files to another volume.
  3. Symlink the files back into ~/.codex/archived_sessions.
  4. Open Codex Desktop and interact with the archived thread list or try to continue/unarchive one of those old threads.
  5. Observe slow/spinning/locked Desktop behavior instead of a bounded per-thread error.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗