[Windows] thread/archive schedules one rollout twice when SQLite uses a verbatim path alias
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:
- Create one valid minimal session_meta rollout under sessions/YYYY/MM/DD.
- Create a consistent test state database containing the synthetic thread.
- Store its rollout_path using the verbatim Windows spelling shown above.
- Call the official app-server thread/archive JSON-RPC method.
- Observe the exact os error 2 and verify rollback leaves the source active.
- Reset the isolated fixture.
- Change only the synthetic rollout_path to the ordinary C:\... spelling.
- Call the same binary with the same thread/archive request.
- 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:
- https://github.com/openai/codex/issues/25713
- https://github.com/openai/codex/issues/37058
- https://github.com/openai/codex/issues/23851
- https://github.com/openai/codex/issues/24944
- https://github.com/openai/codex/issues/23002
Privacy
This report intentionally omits real task IDs, project names, user paths, chat content, logs, credentials, and raw rollout data.
11 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I independently reproduced this on a real local thread, and the behavior matches the duplicate-physical-rollout explanation in this issue.
Environment
26200OpenAI.Codex 26.818.2441.0codex-cli 0.148.0-alpha.21Real-thread A/B evidence
thread/archivefailed 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)
PRAGMA integrity_checkreturnedok.``
text
``rollout_path = \\?\C:\Users\<user>\.codex\sessions\...
cwd = \\?\<drive>:\<project>
The persisted
session_meta.cwdused the equivalent ordinary path without the\\?\prefix.\\?\from that thread'srollout_pathandcwd.thread/archiveoperation immediately succeeded. The rollout moved toarchived_sessions, the database recordedarchived=1, and the active source disappeared. A subsequent officialthread/deletealso 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:
rollout_pathvalues and 7 verbatimcwdvalues.rollout_pathvalues back into two active threads.realtime_voicethread failed archive after its path was rewritten. Normalizingrollout_path + cwdimmediately 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.tomlor application binaries were modified.Independent confirmation on a real local thread; this matches the verbatim-path alias failure described here.
Environment
2620026.818.2441.00.148.0-alpha.21Observed behavior
thread/archiveand 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)
Read-only local validation
state_5.sqlitepassedPRAGMA quick_checkwithok.archived=0andarchived_at=NULL.``
text
``\\?\C:\Users\<user>\.codex\sessions\YYYY\MM\DD\rollout-...jsonl
cwdalso used the\\?\prefix.archived_sessionsexisted, 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.21build and supports the duplicate-physical-rollout / ordinary-vs-verbatim path identity diagnosis.@Yifo98 Thank you very much — your workaround solved the archive problem here.
After creating a full rollback backup, I normalized only
rollout_pathandcwdby removing the leading\\?\immediately before each officialthread/archivecall. 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!
Independent confirmation from another Windows installation.
Environment:
26.814.5517.010.0.26200.9168%USERPROFILE%\.codexObserved on two unrelated local threads:
threads.rollout_pathvalues use the verbatim\\?\C:\...\sessions\...\rollout-....jsonlform;archived_sessionsexists and is writable;PRAGMA quick_checkpasses for the state databases.The official
thread/archiveaction fails reproducibly with:After each failure there is no partial mutation: the rollout remains in
sessions, no archived copy appears, and the row remainsarchived=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/readthen succeeded, butthread/archivestill failed with the sameos 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
mainis 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.Read-only verification against current
main: PR #39256 was merged asfa9a05f2d25f95b39cf365e77cb10f87e8719185, 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 thatmaincontains 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 equivalentalternate/..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-server0.149.0-alpha.4.1, using both synthetic ordinary/verbatim-path controls and three real unloaded threads. Earlier reports show Desktop26.818.2872.0remained affected. Together, that brackets the rollout and confirms that the source fix has reached a current Desktop build, not onlymain.I’m seeing what looks like the same archive failure on Windows in Codex Desktop.
Environment / symptoms:
:danger-full-access.jsonlfiles exist under the normal Codexsessionsdirectoryarchived_sessionsI also inspected the local
state_5.sqlitedatabase in read-only mode. The affected rows in thethreadstable havearchived = 0,archived_at = NULL, and theirrollout_pathvalues are stored in Windows verbatim-path form, e.g.: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.
Independent confirmation on a real Windows thread, with an additional recovery path.
Environment
Microsoft Windows NT 10.0.26200.0OpenAI.Codex 26.818.2872.0session_metareportscli_version = 0.148.0-alpha.15notLoaded; its only turn had previously been interruptedObserved failure
Both the Desktop Archive action and the supported
thread/archiveoperation failed with:Read-only validation showed:
thread/readparsed it successfully;archived_sessionsexisted;\\?\C:\..., while the same file was present at the ordinaryC:\...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:
sessions/YYYY/MM/DDtoarchived_sessions.thread/unarchiveoperation. It succeeded.thread/archiveoperation. It succeeded.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 package26.818.2872.0still 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.
Independent reproduction on the currently offered Microsoft Store build:
OpenAI.Codex 26.818.2872.00.148.0-alpha.21thread/archivewith the exactos error 2.archived_sessionsexists.thread/archiveprotocol through an older locally availablecodex-cli 0.145.0succeeds for the same thread data. The current0.148.0-alpha.21backend 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 package26.818.2872.0remains affected even though #39256 is merged onmain.No task IDs, titles, account identifiers, private paths, logs, credentials, or conversation contents are included.
Independent confirmation from Codex Desktop on Windows, with some additional lifecycle evidence that may help verify the fix.
Environment
26.814.5517.026.814.419570.148.0-alpha.15Observed archive sequence
For an idle, already-loaded thread, a
thread/archiverequest produces this sequence in under a second:Submission ... op: ShutdownShutting down Codex instanceAgent loop exitedcodex_app_server::thread_statelistener teardown withhad_listener=true had_active_turn=falsearchived=0, while its SQLiterollout_pathhas 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
rollout_pathvalues by removing the\\?\prefix.thread/archiveroute.\\?\prefix again. Every corresponding rollout file still existed.codex archiveCLI route subsequently succeeded for that thread.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
fa9a05f2d25f95b39cf365e77cb10f87e8719185was reported as merged. Is that change expected to cover the shutdown-time repersistence described above, and which Microsoft Store build first includes it?Resolved and verified end-to-end on the current Windows Desktop build.
Environment:
26.818.5229.0Codex Desktop/0.149.0-alpha.4.1Validation performed:
CODEX_HOME, the original Windows verbatim-path reproduction and an ordinary-path control both archived successfully through the official app-serverthread/archivemethod.0, archived rollout count1, and the isolated SQLite row becamearchived=1with a consistent archived path.\\?\form were each archived exactly once through the official archive interface.0, archived rollout count1, andarchived=1for 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.0passes real end-to-end acceptance on this machine.Thanks to everyone who helped reproduce and narrow this down.