openai / openai/codex

Codex Desktop Windows: archive fails with os error 2 when state_5.sqlite rollout_path uses \\?\ prefix

Open
#39,669 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

app bug session windows-os
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

On Windows, local Codex Desktop thread archiving can fail with:

failed to archive session: thread-store internal error: failed to archive thread: The system cannot find the file specified. (os error 2)

On my machine this reproduces when state_5.sqlite.threads.rollout_path points at an existing rollout JSONL using a Windows extended-length path prefix (\\?\C:\...). The rollout file exists and is readable. If I back up state_5.sqlite, remove only the leading \\?\ prefix from that thread row's rollout_path (and cwd for consistency), then immediately call archive again, the same thread archives successfully.

This looks related to the existing archive/session path-consistency issue family, but I did not find an exact report for the rollout_path = \\?\... trigger on Windows.

Environment

  • Platform: Windows 11 x64
  • Codex Desktop client observed in logs: 26.814.41957
  • Affected local thread rows include cli_version = 0.148.0-alpha.15 and 0.148.0-alpha.9
  • Local state database: %USERPROFILE%\.codex\state_5.sqlite
  • Logs database: %USERPROFILE%\.codex\logs_2.sqlite
  • Active sessions directory: %USERPROFILE%\.codex\sessions\...
  • Archive directory: %USERPROFILE%\.codex\archived_sessions\...

Reproduction From Local State

For a completed/notLoaded local thread:

  1. Confirm the thread row is unarchived and the rollout path starts with \\?\:
SELECT
  id,
  archived,
  quote(substr(rollout_path, 1, 6)) AS rollout_prefix,
  quote(substr(cwd, 1, 6)) AS cwd_prefix,
  substr(rollout_path, 1, 100) AS rollout_head,
  cli_version
FROM threads
WHERE id = '<thread-id>';

Observed before repair:

archived       = 0
rollout_prefix = '\\?\C:'
cwd_prefix     = '\\?\C:'
rollout_head   = \\?\C:\Users\<user>\.codex\sessions\YYYY\MM\DD\rollout-...-<thread-id>.jsonl
cli_version    = 0.148.0-alpha.15
  1. Confirm the physical rollout JSONL exists and is readable after stripping the \\?\ prefix.
  2. Try to archive the thread from Codex Desktop / app thread API.

Observed error:

failed to archive session: thread-store internal error: failed to archive thread: The system cannot find the file specified. (os error 2)
  1. Back up state_5.sqlite.
  2. Remove only the leading \\?\ prefix for that one notLoaded/idle thread:
UPDATE threads
SET
  rollout_path = CASE
    WHEN substr(rollout_path, 1, 4) = '\\?\' THEN substr(rollout_path, 5)
    ELSE rollout_path
  END,
  cwd = CASE
    WHEN substr(cwd, 1, 4) = '\\?\' THEN substr(cwd, 5)
    ELSE cwd
  END
WHERE id = '<thread-id>' AND archived = 0;
  1. Run PRAGMA integrity_check; and confirm ok.
  2. Archive the same thread again.

Observed after repair:

archived = 1
rollout_path = C:\Users\<user>\.codex\archived_sessions\rollout-...-<thread-id>.jsonl
source_exists = false
archived_exists = true

Important Observations

  • This is not limited to old sessions. On my machine, new/current 0.148.0-alpha.15 rows can also have rollout_path = \\?\....
  • A one-time bulk SQL normalization is not durable. Some rows that were normalized earlier later got the \\?\ prefix written back after the thread was resumed or updated.
  • cwd = \\?\... alone does not appear to be enough to break archive. In my local DB, many successfully archived rows still had cwd with a \\?\ prefix. The direct failure indicator was rollout_path = \\?\....
  • For successfully archived rows in my local DB, archived rollout_path values were normal paths under archived_sessions, not \\?\....
  • Recent logs also showed repeated Windows long-path related hook failures:
after_agent hook failed; continuing ... hook_name=legacy_notify error=The filename or extension is too long. (os error 206)

This hook error is not the same as the archive os error 2, but it suggests the current Windows path/string handling path has adjacent long-path issues.

Expected Behavior

Archiving should work when the thread's rollout JSONL exists and is readable, regardless of whether the persisted path uses a normal Windows path or an extended-length \\?\ path.

At minimum, Codex should normalize supported Windows path forms consistently before scope validation / filename extraction / rename, and should avoid persisting a path format that the archive path cannot later handle.

Actual Behavior

The archive operation fails with os error 2 while the rollout file exists. Normalizing the one affected row's rollout_path from \\?\C:\... to C:\... makes the same archive operation succeed immediately.

Why This May Point To Thread Store Path Handling

The current archive implementation resolves a current rollout path, scopes it under sessions, validates the rollout filename, then renames the selected rollout into archived_sessions and updates SQLite metadata:

https://github.com/openai/codex/blob/main/codex-rs/thread-store/src/local/archive_thread.rs

The observed behavior suggests one of those path handling steps is not treating \\?\C:\... and C:\... as equivalent on Windows.

Related Issues

  • #26012 - Windows archive/restore path inconsistency with The system cannot find the file. (os error 2)
  • #25541 - Windows archive UI / sidebar reconciliation issues
  • #36531 - archive depends on filesystem rename and can fail with a low-level OS error
  • #20317 - sessions vs archived_sessions path mismatch after archive/restore
  • #33860 - unarchive can mutate storage then still return an internal error
  • #27202 - archived local thread exists in SQLite but disappears from active and Archived UI

Privacy Note

I intentionally redacted real user names, local project paths, thread titles, and business prompts. I can provide additional redacted SQL/log excerpts if maintainers specify which fields would be useful.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with codex-rs/thread-store/src/local/archive_thread.rs and trace how rollout_path is resolved, scope-checked, filename-validated, and renamed on Windows. Reproduce the failure using a rollout_path with a \?\ prefix, comparing it with the documented SQL normalization. Done means an existing readable rollout archives successfully and SQLite metadata points to the archived path without requiring a manual database edit.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sqlite
Domain
backend, databases, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.