[Windows] thread/archive schedules one rollout twice when SQLite uses a verbatim path alias

Open 💬 11 comments Opened Aug 20, 2026 by lymiran
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

  • Originally reproduced with Codex Desktop app-server 0.148.0-alpha.15 in the 26.814.x Desktop package line. - Still reproduced after the official update to Desktop package 26.818.2441.0, which bundles app-server 0.148.0-alpha.21. - Updated bundled codex.exe SHA-256: 18FBF51F77ADFC543C9D86C78C0A54553F89BA79236ED8B0A3C48E2A3B4F010E.

What subscription do you have?

Not relevant to this local filesystem operation.

What platform is your computer?

Windows 11 x64, Microsoft Windows NT 10.0.26200.0.

What issue are you seeing?

On Windows, thread/archive fails with:

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

The rollout exists and is readable. The failure occurs when SQLite stores the rollout path using the Windows verbatim spelling:

\\?\C:\synthetic\codex-home\sessions\YYYY\MM\DD\rollout-....jsonl

while RolloutReferenceIndex::scan discovers the same physical file using the ordinary spelling:

C:\synthetic\codex-home\sessions\YYYY\MM\DD\rollout-....jsonl

In rust-v0.148.0, archive_thread_with_paths deduplicates these paths with raw PathBuf equality:

if !rollout_paths.contains(&selected_rollout_path) {
rollout_paths.push(selected_rollout_path.clone());
}

Both aliases therefore enter rollout_moves. scoped_rollout_path resolves both aliases to the same physical source file. The first rename succeeds; the second rename tries to move the now-missing source, returns os error 2, and rollback restores the first move. The user sees an archive failure even though the source file was present.

What steps can reproduce the bug?

The following A/B was run only in an isolated temporary CODEX_HOME with a synthetic thread and rollout:

  1. Create one valid minimal session_meta rollout under sessions/YYYY/MM/DD.
  2. Create a consistent test state database containing the synthetic thread.
  3. Store its rollout_path using the verbatim Windows spelling shown above.
  4. Call the official app-server thread/archive JSON-RPC method.
  5. Observe the exact os error 2 and verify rollback leaves the source active.
  6. Reset the isolated fixture.
  7. Change only the synthetic rollout_path to the ordinary C:\... spelling.
  8. Call the same binary with the same thread/archive request.
  9. Archive succeeds, the rollout moves once to archived_sessions, and the isolated metadata records archived=1.

A separate Rust std::fs::rename probe confirmed that one rename can mix ordinary and verbatim path spellings successfully. The namespace itself is not the failing invariant; duplicate physical-file scheduling is.

No real Codex database, rollout, task, installation, or configuration was modified for this reproduction.

The isolated verbatim-path case was rerun after updating to Desktop 26.818.2441.0 / app-server 0.148.0-alpha.21. It still returned the same thread-store os error 2. Verification after the failure found one active synthetic rollout, zero archived synthetic rollouts, and the isolated SQLite row remained archived=0 with no archived_at value. Testing stopped on that first failure; no real task was used.

What is the expected behavior?

Archive should identify rollout files by normalized/canonical filesystem identity before deduplication and before constructing rollout_moves. One physical rollout must be moved exactly once regardless of whether discovery and SQLite use ordinary and verbatim Windows path aliases.

Additional information

  • Normalize or canonicalize filesystem identity before deduplicating rollout_paths.
  • Ensure the selected rollout maps to the deduplicated destination.
  • Add a Windows regression where the reference-index scan supplies an ordinary path and SQLite supplies the equivalent \\?\ path.
  • Assert that exactly one move is scheduled and thread/archive succeeds.

The current main branch appears to use a newer single-path archive flow than rust-v0.148.0. Please confirm whether that refactor already fixes this case and, if so, which Desktop build contains the fix. A dedicated Windows alias regression would prevent recurrence.

Source pointers

  • Affected tagged implementation:

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

  • Current main implementation:

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

Duplicate search

No matching existing issue was found. These reports are related to archive/session handling but describe different failure modes:

Privacy

This report intentionally omits real task IDs, project names, user paths, chat content, logs, credentials, and raw rollout data.

View original on GitHub ↗

11 Comments

github-actions[bot] contributor · 7 days ago

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

  • #39239
  • #39689
  • #39669
  • #39600
  • #39675

Powered by Codex Action

Yifo98 · 7 days ago

I independently reproduced this on a real local thread, and the behavior matches the duplicate-physical-rollout explanation in this issue.

Environment

  • Windows 11 x64, build 26200
  • Microsoft Store package OpenAI.Codex 26.818.2441.0
  • Bundled codex-cli 0.148.0-alpha.21

Real-thread A/B evidence

  1. thread/archive failed three consecutive times with JSON-RPC -32603:

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

  1. The source rollout existed and was readable. It contained 160 valid JSONL lines and zero parse failures. The archive directory existed, no same-name destination existed, there was no writer lock, and PRAGMA integrity_check returned ok.
  1. SQLite stored aliases in verbatim form:

``text
rollout_path = \\?\C:\Users\<user>\.codex\sessions\...
cwd = \\?\<drive>:\<project>
``

The persisted session_meta.cwd used the equivalent ordinary path without the \\?\ prefix.

  1. After backing up the database and rollout, I changed only the path spelling by removing the leading \\?\ from that thread's rollout_path and cwd.
  1. The same official thread/archive operation immediately succeeded. The rollout moved to archived_sessions, the database recorded archived=1, and the active source disappeared. A subsequent official thread/delete also succeeded and left zero database rows, rollout files, or active/archived list matches for that thread.

The alias is recreated

This is not only a one-time stale migration:

  • A database scan found 3 verbatim rollout_path values and 7 verbatim cwd values.
  • Normalizing all affected rows reduced both counts to zero.
  • Subsequent App Server interactions wrote verbatim rollout_path values back into two active threads.
  • An older realtime_voice thread failed archive after its path was rewritten. Normalizing rollout_path + cwd immediately before the request made archive succeed; unarchive also succeeded.

This suggests the current writer/resume/index-repair path continues to reintroduce the ordinary/verbatim alias pair, so fixing archive deduplication alone may not prevent the inconsistent representation from recurring.

No raw logs, task IDs, user paths, conversation content, credentials, database files, or rollout files are attached. No config.toml or application binaries were modified.

ChouMax-1989 · 7 days ago

Independent confirmation on a real local thread; this matches the verbatim-path alias failure described here.

Environment

  • Windows 11 Enterprise LTSC x64, build 26200
  • Codex Desktop MSIX 26.818.2441.0
  • Bundled app-server / CLI 0.148.0-alpha.21

Observed behavior

  • The normal Desktop archive action failed 7 times through the sidebar/recent-tasks UI.
  • Every request reached thread/archive and returned JSON-RPC -32603:

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

  • At least one attempt occurred after the latest turn had completed and the thread view had transitioned inactive, so this was not caused by trying to archive an in-progress turn.
  • The thread remained visible and unarchived after every attempt.

Read-only local validation

  • state_5.sqlite passed PRAGMA quick_check with ok.
  • The affected row remained archived=0 and archived_at=NULL.
  • The stored rollout path used the verbatim form:

``text
\\?\C:\Users\<user>\.codex\sessions\YYYY\MM\DD\rollout-...jsonl
``

  • The stored cwd also used the \\?\ prefix.
  • The referenced rollout existed, was readable, and was non-empty (about 2.2 MB).
  • archived_sessions existed, but no archived copy was created.

No database rows or session files were modified. Raw logs, thread IDs, task titles, conversation content, account details, and full local paths are intentionally omitted.

This provides another independent real-world reproduction on the same 26.818.2441.0 / 0.148.0-alpha.21 build and supports the duplicate-physical-rollout / ordinary-vs-verbatim path identity diagnosis.

lymiran · 7 days ago

@Yifo98 Thank you very much — your workaround solved the archive problem here.

After creating a full rollback backup, I normalized only rollout_path and cwd by removing the leading \\?\ immediately before each official thread/archive call. I tested six affected legacy threads individually, starting with one pilot. All six archived successfully on the first attempt after normalization.

Post-checks confirmed archived=1, no active rollout, exactly one archived rollout, and matching SHA-256 for every thread. I was then able to delete the archived tasks from Codex Settings successfully.

This confirms the workaround is effective, although the underlying path-writer/deduplication bug still needs an official fix. I really appreciate your detailed reproduction and guidance — thank you!

projectscentr2 · 7 days ago

Independent confirmation from another Windows installation.

Environment:

  • Codex Desktop package: 26.814.5517.0
  • Windows x64 build: 10.0.26200.9168
  • Local host/thread store under %USERPROFILE%\.codex

Observed on two unrelated local threads:

  • both SQLite threads.rollout_path values use the verbatim \\?\C:\...\sessions\...\rollout-....jsonl form;
  • each source rollout exists at the exact recorded path and is readable;
  • archived_sessions exists and is writable;
  • no same-name destination exists;
  • thread CWDs exist;
  • the rollout files are not locked;
  • PRAGMA quick_check passes for the state databases.

The official thread/archive action fails reproducibly with:

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

After each failure there is no partial mutation: the rollout remains in sessions, no archived copy appears, and the row remains archived=0, archived_at=NULL.

One of the two threads initially had a separately missing rollout. I restored it from a byte-identical, SHA-256-verified backup to the exact catalog path. thread/read then succeeded, but thread/archive still failed with the same os error 2. This isolates the current archive failure from missing conversation content and is consistent with the duplicate physical-file scheduling described in this issue.

A full Windows reboot and Codex restart did not change the result. No manual database workaround was applied; the affected threads remain intact and unarchived.

Could the team confirm whether the canonical-source deduplication now visible on main is intended to fix this case, and which Windows Desktop package will include it? A supported repair/retry path for already affected rows would also be very helpful.

dajiaohuang · 7 days ago

Read-only verification against current main: PR #39256 was merged as fa9a05f2d25f95b39cf365e77cb10f87e8719185, and its stated failure mode matches this report: a non-canonical SQLite rollout path can resolve to a rollout already found on disk, causing the same source file to be scheduled twice. The merged change canonicalizes each source before deduplicating archive and unarchive moves, and adds metadata-backed tests using equivalent rollout paths. This strongly indicates that main contains the source-level fix. I could not determine from the public repository which Windows Desktop package first includes that commit; the added regression uses an equivalent alternate/.. path rather than the Windows \\?\ spelling specifically.

Update (2026-08-22): the 0.149.0 release notes include #39256, and the issue reporter has now verified the exact case end-to-end on Desktop 26.818.5229.0 / app-server 0.149.0-alpha.4.1, using both synthetic ordinary/verbatim-path controls and three real unloaded threads. Earlier reports show Desktop 26.818.2872.0 remained affected. Together, that brackets the rollout and confirms that the source fix has reached a current Desktop build, not only main.

wojciechsumlet · 7 days ago

I’m seeing what looks like the same archive failure on Windows in Codex Desktop.

Environment / symptoms:

  • Windows workstation, Codex Desktop
  • Execution profile is full access / :danger-full-access
  • Restarting both Windows and Codex does not fix it
  • Affected tasks are still visible and readable in the project sidebar
  • The rollout .jsonl files exist under the normal Codex sessions directory
  • They are not present under archived_sessions
  • Attempting to archive from the UI fails, and archiving through the thread tool fails with:
failed to archive session: thread-store internal error: failed to archive thread: The system cannot find the file specified. (os error 2)

I also inspected the local state_5.sqlite database in read-only mode. The affected rows in the threads table have archived = 0, archived_at = NULL, and their rollout_path values are stored in Windows verbatim-path form, e.g.:

\\?\C:\Users\...\.codex\sessions\YYYY\MM\DD\rollout-...jsonl

That lines up with the verbatim-path alias diagnosis in this issue. The local repository involved is clean and synchronized, so this does not appear to be caused by project Git state or normal filesystem permissions.

zhou-zhichao · 7 days ago

Independent confirmation on a real Windows thread, with an additional recovery path.

Environment

  • Windows x64: Microsoft Windows NT 10.0.26200.0
  • Microsoft Store package: OpenAI.Codex 26.818.2872.0
  • The affected rollout's session_meta reports cli_version = 0.148.0-alpha.15
  • Affected thread state before repair: notLoaded; its only turn had previously been interrupted

Observed failure

Both the Desktop Archive action and the supported thread/archive operation failed with:

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

Read-only validation showed:

  • the rollout JSONL existed, was readable, and thread/read parsed it successfully;
  • the original projectless CWD still existed;
  • archived_sessions existed;
  • no same-name archive destination existed;
  • the thread had no writer lock;
  • recorder logs resolved the rollout through the Windows verbatim form \\?\C:\..., while the same file was present at the ordinary C:\... spelling.

This is consistent with the duplicate physical-rollout / ordinary-vs-verbatim path diagnosis in this issue.

Recovery experiment

I used a recovery sequence that did not edit SQLite:

  1. Move exactly the affected rollout once from sessions/YYYY/MM/DD to archived_sessions.
  2. Verify SHA-256 was unchanged.
  3. Call the official thread/unarchive operation. It succeeded.
  4. Immediately call the official thread/archive operation. It succeeded.
  5. Verify the thread was absent from the active list and present in the archived list.

Before this re-registration sequence, repeated native archive calls failed. After it, native archive succeeded with the same rollout and filename. This further isolates the failure to path identity/catalog state rather than rollout corruption, permissions, missing CWD, or the interrupted turn itself.

Since PR #39256 is reported as merged on main, this confirms that Store package 26.818.2872.0 still exhibits the affected behavior (or does not yet contain the fix).

No task IDs, usernames, absolute local paths, titles, conversation content, credentials, databases, or rollout contents are included.

xzessdnied · 7 days ago

Independent reproduction on the currently offered Microsoft Store build:

  • Windows x64
  • Desktop package: OpenAI.Codex 26.818.2872.0
  • Bundled app-server: 0.148.0-alpha.21
  • Multiple completed/idle local threads fail through both the Desktop Archive action and thread/archive with the exact os error 2.
  • For the affected threads, the rollout files exist and are readable, and archived_sessions exists.
  • Restarting the app does not change the result.
  • Running the same official thread/archive protocol through an older locally available codex-cli 0.145.0 succeeds for the same thread data. The current 0.148.0-alpha.21 backend then correctly lists the thread as archived.

This A/B further isolates the failure to the current archive implementation/catalog path handling rather than missing rollout content or filesystem permissions. The Windows Store updater currently reports NoUpdates, so package 26.818.2872.0 remains affected even though #39256 is merged on main.

No task IDs, titles, account identifiers, private paths, logs, credentials, or conversation contents are included.

mmprojects2 · 6 days ago

Independent confirmation from Codex Desktop on Windows, with some additional lifecycle evidence that may help verify the fix.

Environment

  • Windows x64
  • Microsoft Store package: 26.814.5517.0
  • Desktop client version recorded in logs: 26.814.41957
  • Bundled app-server/session metadata: 0.148.0-alpha.15

Observed archive sequence
For an idle, already-loaded thread, a thread/archive request produces this sequence in under a second:

  1. Submission ... op: Shutdown
  2. Shutting down Codex instance
  3. Agent loop exited
  4. codex_app_server::thread_state listener teardown with had_listener=true had_active_turn=false
  5. The thread remains archived=0, while its SQLite rollout_path has been written using the verbatim-path alias (\\?\C:\Users\<redacted>\.codex\sessions\...).

The referenced rollout exists and is readable using both the ordinary and verbatim path spellings. The archive error is The system cannot find the file specified. (os error 2).

Durability / reproduction evidence

  • I made a consistent SQLite backup, then normalized affected rollout_path values by removing the \\?\ prefix.
  • Dormant/not-loaded threads then archived successfully through the official app thread/archive route.
  • This was not durable: after 26 records were normalized, continued normal use of the running app resulted in 14 unarchived records carrying the \\?\ prefix again. Every corresponding rollout file still existed.
  • In a six-thread test, five dormant threads archived successfully after normalization. One already-loaded thread still failed because the path alias was repersisted during shutdown. The older codex archive CLI route subsequently succeeded for that thread.
  • No transcript loss or partial move was observed: source rollouts remained under sessions, no duplicate archive files appeared, and SQLite integrity remained OK.

Rapidly clicking several archive actions makes the symptom appear clustered, but each failure follows the same sub-second shutdown/path-rewrite sequence. This does not appear to be missing files or user click rate; it appears to be path-alias persistence/deduplication around shutdown.

I see that PR #39256 / commit fa9a05f2d25f95b39cf365e77cb10f87e8719185 was reported as merged. Is that change expected to cover the shutdown-time repersistence described above, and which Microsoft Store build first includes it?

lymiran · 6 days ago

Resolved and verified end-to-end on the current Windows Desktop build.

Environment:

  • Codex Desktop package: 26.818.5229.0
  • Bundled app-server: Codex Desktop/0.149.0-alpha.4.1
  • Codex 0.149.0 changelog includes #39256, “Deduplicate rollout moves when archiving threads.”

Validation performed:

  1. In a fully synthetic temporary CODEX_HOME, the original Windows verbatim-path reproduction and an ordinary-path control both archived successfully through the official app-server thread/archive method.
  2. In both isolated cases, exactly one rollout move occurred: active rollout count 0, archived rollout count 1, and the isolated SQLite row became archived=1 with a consistent archived path.
  3. After separate explicit approval, three real unloaded tasks whose persisted rollout paths used the \\?\ form were each archived exactly once through the official archive interface.
  4. All three appeared in the official archived-task list. Read-only verification found active rollout count 0, archived rollout count 1, and archived=1 for every task.

No real SQLite rows were manually edited, and no rollout files were manually moved or deleted.

Conclusion: #39256 / the 0.149 line fixes the exact duplicate physical-file scheduling reproduction reported here, and package 26.818.5229.0 passes real end-to-end acceptance on this machine.

Thanks to everyone who helped reproduce and narrow this down.