Windows: `thread/archive` fails with "os error 2" after `thread/resume` stores a `\\?\` (verbatim) rollout_path — same file queued twice
Open 💬 26 comments Opened Aug 18, 2026 by shaded0
💡 Likely answer: A maintainer (github-actions[bot], contributor)
responded on this thread — see the highlighted reply below.
Summary
On Windows, once a thread has been resumed, archiving it 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 file exists and is readable. Root cause is a path-equality mismatch in archive_thread_with_paths that causes the same rollout file to be renamed twice.
Environment
- Codex desktop 26.814.5167.0 (release 26.814.41407), bundled CLI 0.148.0-alpha.15
- Windows 11 (build 26200)
Repro
- Open (resume) any existing thread in the desktop app.
threads.rollout_pathinstate_5.sqliteis now stored as\\?\C:\Users\<user>\.codex\sessions\...\rollout-...jsonl(verbatim prefix — looks likestd::fs::canonicalizeoutput). Threads that have not been opened keep the plainC:\Users\<user>\.codex\sessions\...\rollout-...jsonlform.- Archive that thread → error above. The file is still in
sessions/afterward. - Workaround that confirms the diagnosis: strip the
\\?\prefix from that row'srollout_path, then archive without re-opening → succeeds. Re-opening the thread re-introduces the prefix and the failure.
Analysis (codex-rs/thread-store/src/local/archive_thread.rs)
In archive_thread_with_paths:
rollout_pathscomes fromowned_rollout_paths_from_index(&reference_index, ...)— a filesystem scan → plainC:\...paths.selected_rollout_pathcomes fromthread_rollout_resolver::resolve_current→ the SQLite row →\\?\C:\....if !rollout_paths.contains(&selected_rollout_path) { rollout_paths.push(selected_rollout_path) }comparesPathBufs byte-wise, so the verbatim and non-verbatim forms of the same file are treated as different and both are queued.- Each is then passed through
scoped_rollout_path(helpers.rs), which canonicalizes both to the identical source and computes the identical destination. - First
std::fs::renamesucceeds; the second fails withNotFoundbecause the source was just moved.restore_rollout_movesthen rolls the first move back — hence the file "still exists" and the misleading error.
Suggested fix (either/both)
- Dedup
rollout_movesafter canonicalization (compare canonical source paths, or dedup by rollout id/filename) rather thancontainson mixed-form paths beforehand. - Don't persist verbatim (
\\?\) paths on resume; store the same form the scanner produces (e.g.dunce::canonicalize, or strip the verbatim prefix on Windows).
26 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Independent reproduction on Windows with Codex Desktop
26.814.5167.0.Read-only local inspection found:
\\?\C:\...\-prefixedrollout_pathvalues.C:\...\rollout paths archived successfully during the same app run.This independently corroborates the path-normalization/double-move diagnosis. No usernames, private paths, conversation IDs, titles, contents, or raw logs are included, and no local state was modified during diagnosis.
Independent confirmation from another Windows installation, including a successful two-thread repair that matches this diagnosis.
Environment
OpenAI.Codex_26.814.5167.0_x64__2p2nqsd0c76g010.0.26200(build26200)C:\Users\rikad\.codexcli_version = 0.147.0-alpha.6.5from creation.Affected threads
019fe60c-e441-7333-aabb-f7e7bd6f8817\\?\C:\Users\rikad\.codex\sessions\2026\08\09\rollout-2026-08-09T11-23-52-019fe60c-e441-7333-aabb-f7e7bd6f8817.jsonl019feae1-be46-7213-bd62-9823a5f84444\\?\C:\Users\rikad\.codex\sessions\2026\08\10\rollout-2026-08-10T09-54-50-019feae1-be46-7213-bd62-9823a5f84444.jsonlFor both threads, the rollout file existed and
C:\Users\rikad\.codex\archived_sessionsexisted, butthread/archivereturned:Before the local repair, the database distribution was:
\\?\prefixConfirmed workaround
For only the two IDs above, I removed the leading
\\?\fromstate_5.sqlite.threads.rollout_pathwhile leaving the actual files untouched, then immediately called the normalthread/archiveoperation without reopening either thread.Both archive calls then succeeded. Each row became
archived=1, each rollout moved intoarchived_sessions, the destination files existed, and both IDs disappeared from the normal thread list.This independently confirms that the stored verbatim path form is the trigger and that normalizing it before archive/deduplication resolves the failure. We can provide the complete Desktop log and additional affected rows if useful.
Confirmed independently on Windows with the same failure mode.
Environment:
26.814.5167.010.0.26200Observed repeatedly from the UI and native archive path:
Read-only local verification of the affected thread shows:
threads.rollout_pathbegins with the Windows verbatim prefix\\?\C:\....archived = 0after every attempt.This matches the duplicate-move/path-normalization analysis in this issue very closely. No raw logs, private paths, credentials, thread IDs, or conversation content are included here.
Confirmed independently on Windows with the same path-form mismatch.
Environment:
26.814.5167.00.148.0-alpha.1510.0.26200notLoadedObserved behavior:
Read-only verification:
session_meta.session_idmatches the cataloged thread.archived_sessionsexists.state_5.sqlite.threads.rollout_pathbegins with\\?\C:\....C:\...paths, and recent successfully archived rows also use plain paths.No project files, conversation content, usernames, local project paths, or thread IDs are included here. This reproduction is consistent with the double-move/path-deduplication analysis in this issue.
Another independent two-thread confirmation on Windows, with a controlled repair that matches the double-move/path-normalization diagnosis.
Environment
26.814.5167.010.0.26200cli_version = 0.148.0-alpha.9Evidence before repair
For two separate completed threads on the same installation:
thread/archiveconsistently failed withfailed to archive thread: The system cannot find the file specified. (os error 2).notLoadedand had no spawn-edge dependency.threads.rollout_pathused the\\?\C:\...form andarchived = 0.codex doctorreported the state DB integrity asok, exact rollout-file/DB-row parity, and zero stale rows, archive mismatches, duplicate paths, duplicate thread IDs, malformed filenames, or scan errors.Controlled repair
For each thread, I first made a consistent SQLite online backup, then changed only that row's
rollout_pathfrom\\?\C:\...toC:\..., leaving the rollout file untouched. I immediately called the normalthread/archiveoperation without reopening the thread.Both archive operations then succeeded. Each rollout was moved by Codex into
archived_sessions, each row became archived, and the rollout digest was unchanged across the move. A post-repaircodex doctorcheck still reported exact filesystem/DB parity and zero archive mismatches or stale rows.As a read-only blast-radius check, 73 of 228 current thread rows on this installation still used the verbatim prefix at the time of inspection. This does not claim that all 73 have been tested or will fail, but it suggests the persisted path form is not rare.
No usernames, absolute user paths, thread IDs, titles, project names, conversation content, rollout contents, raw logs, database files, credentials, or digests are included here. This further corroborates that the files are not missing and that normalizing/deduplicating equivalent Windows paths before scheduling rollout moves should address the failure.
Additional independent reproduction on Codex Desktop for Windows (MSIX package
26.814.5167.0, ARM64): archiving fails for every tested local task, not just one conversation.Observed error from the Desktop log for each
thread/archiverequest:Read-only checks confirm the affected rollout JSONL files still exist under the dated
~/.codex/sessions/YYYY/MM/DD/tree, and~/.codex/archived_sessionsexists and is writable. Restarting Windows and using Windows App Repair did not change the behavior.This is consistent with the mixed normal/verbatim (
\\?\\) Windows rollout-path handling described in this issue. No task content, credentials, or local usernames are included here.Confirmed that this is still reproducible on the latest Microsoft Store package available to me:
26.814.5517.0(Store-signed, package statusOk)26.814.4195710.0.26200Additional controlled evidence:
threads.rollout_pathentries had been normalized to ordinaryC:\...paths and the\\?\-prefix count was verified as zero.thread/archiveoperation then succeeded for a repaired test thread.26.814.5517.0, launching that package, and resuming two active threads, both SQLite rows were written again with the verbatim\\?\C:\...form in bothcwdandrollout_path.integrity_checkremainsok; every referenced rollout JSONL exists and is non-empty.This reproduces the state transition described in this issue and indicates that
26.814.5517.0still contains the resume/writer vs. archive path-form mismatch. No usernames, absolute paths, thread IDs, task content, raw logs, or database files are included here.Independent confirmation on Windows x64 with Codex Desktop
26.814.5167.0.Two unrelated local project threads reproduce the same archive failure:
Read-only checks before each attempt:
state_5.sqlite.threads.rollout_pathvalues use the\\?\C:\...verbatim form.archived_sessionsexists; source and destination are on the same volume; no destination-name collision exists.archived = 0after failure.PRAGMA quick_checkreturnsok.The second affected thread is from the primary project checkout rather than the managed worktree used by the first, so missing Git-worktree metadata is not required to reproduce the failure. This independently supports the mixed-path/double-move diagnosis in the issue body.
Additional confirmation from Codex Desktop on Windows.
01a018a3-51b5-7763-af37-a2c3b6cc28e226.814.41407state_5.sqlite.threads.rollout_pathuses the extended Windows path form\\?\C:\Users\<user>\.codex\sessions\...\rollout-...jsonl.notLoadedstill returns:failed to archive thread: The system cannot find the file specified. (os error 2)archivedremains0, the original rollout remains insessions, no archived copy is created, and no writer lock remains.thread not foundwhen continuing the conversation until the app is restarted.This behavior closely corroborates the duplicate-move/path-normalization diagnosis described in this issue. The rollback preserves the rollout file, but the archive fails and can temporarily leave the runtime thread unresolvable.
Independent confirmation after installing the newer Windows MSIX build: the issue is still reproducible. Environment: - Codex Desktop package
26.814.5517.0- app-server0.148.0-alpha.15- Windows 11 Pro x6410.0.26200Two unrelated local threads failed to archive on26.814.5167.0. After updating to26.814.5517.0, retrying one of them still returns: ``text failed to archive session: thread-store internal error: failed to archive thread: Не удается найти указанный файл. (os error 2)`Read-only verification: - the affectedthreads.rollout_pathvalues use the\\?\C:\...form - the referenced rollout JSONL files exist, are readable, and contain the matching session IDs - the rows remainarchived = 0, with no archived duplicate after failure - SQLite integrity checks pass - one affected rollout had previously passed through a local import/sync workflow, while the other had never been touched by it; both fail identically - an older Desktop build (26.810.52044) could resume the same rollout, and archive operations had succeeded before the26.814` update. No database rows or rollout files were modified during this investigation.Additional independent confirmation with a deterministic mitigation/regression test.
Environment
26.814.5167.0Controlled A/B reproduction
state_5.sqlite.threads.rollout_pathstored as\\?\C:\…, the normalthread/archivecall consistently returned:failed to archive thread: The system cannot find the file specified. (os error 2)C:\…made the same archive call succeed immediately.ok.Persistent local mitigation test
As a diagnostic mitigation, I added two SQLite
AFTER INSERT/AFTER UPDATE OF rollout_pathtriggers that strip a leading\\?\prefix. This is not proposed as an end-user workaround; it was used to test whether preventing mixed path forms eliminates the failure.Results:
\\?\path was normalized by the trigger in the same write.rollout_pathrows, all eight rollouts present insessions, no stale archived copies, andPRAGMA integrity_check = ok.This strengthens the conclusion that the failure is caused by mixed Windows path representations rather than missing files, permissions, authentication, or subscription state. Normalizing persisted rollout paths or deduplicating canonical source paths before scheduling renames should prevent the double-move.
Privacy note: no usernames, absolute paths, file or project names, thread IDs or titles, conversation content, database files, or raw logs are included.
Independent read-only confirmation from another Windows installation; the bug is still reproducible on the current Store package.
Environment
26.814.5517.0(package statusOk)0.148.0-alpha.1526200Observed failure
Multiple unrelated threads repeatedly failed through the normal Desktop archive UI on 2026-08-19:
The UI successfully issued each archive request; the failure came from the local thread store.
Read-only verification
threads.rollout_pathstored in the verbatim\\?\C:\...\form.This independently supports the mixed-path/double-move diagnosis in this issue. No usernames, absolute paths, thread IDs, project names, conversation content, credentials, raw logs, or database files are included. No local files or database records were modified during diagnosis.
Additional independent confirmation from the current Windows Store package.
Environment
26.814.5517.0(package statusOk; Store updater reported no newer package)0.148.0-alpha.1526200zh-CNsource = vscodeandhistory_mode = legacyObserved failure
Six archive attempts over approximately eight minutes all returned:
The affected
state_5.sqlite.threads.rollout_pathbegins with the exact Windows verbatim prefix described in the issue body.Read-only verification found:
PRAGMA integrity_checkreturnsok.PRAGMA foreign_key_checkreturns no violations.archived = 0andarchived_at IS NULLafter every attempt.thread/deleterequest succeeded during the same app session, which narrows the failure to the archive path/move logic rather than general filesystem permissions, authentication, or network state.This closely matches the mixed-path/double-move diagnosis in the issue body. No usernames, absolute private paths, thread IDs, titles, conversation contents, credentials, raw logs, or database files are included. No local files or database records were modified during diagnosis.
We have a fix for this. It will be included in the next release.
Additional confirmation on the current Windows Store build.
Environment
26200OpenAI.Codex 26.814.5517.0At
2026-08-19 23:27:52 UTC, a normal Desktop archive action reached the local archive operation and failed with:errorCode=-32603failed to archive thread: The system cannot find the file specified. (os error 2)Read-only verification found:
quick_check = ok.\\?\C:\….This closely matches the path-normalization failure described here and confirms that
26.814.5517.0is still affected. I will retest after the next release containing the announced fix. No local paths, task IDs, titles, conversation content, account data, or raw logs are included, and no local state was modified.Confirming this is exactly what I'm seeing on Windows. The annoying part is that it looks random in the app, but after checking the local state it isn't.
My setup:
Right now I have 10 active user chats and 9 of them have a
\\?\C:\...rollout path. SQLitequick_checkis clean, and every affected JSONL file exists and is readable using either path spelling.One extra data point that may help: I happened to have two backup snapshots of
state_5.sqlitetaken six minutes apart. In the first snapshot, a newly created active chat had a normalC:\...rollout path. In the second snapshot, that exact same row had been rewritten to\\?\C:\.... It was still unarchived, the file had not moved, andupdated_at_mshad only increased by 1. I did not manually edit that chat between the snapshots.I also tested the workaround on three unrelated affected chats: back up the databases, strip only the
\\?\prefix from that chat'srollout_path, then run the bundled archive command. All three archived successfully and moved intoarchived_sessions. Without that normalization, the same chats fail withos error 2.So this does seem to be the resume/refresh path rewrite causing the same physical file to be queued twice, not missing history or a bad rollout file. It would be great if the archive code could dedupe after canonicalization, since otherwise reopening a chat can put it right back into the broken state.
Additional user-visible side effect confirmed on Codex Desktop 26.814.5517.0, bundled app-server 0.148.0-alpha.15, Windows 11 Pro 10.0.26200:
thread/archivefails with-32603 / os error 2.turn/start -32600: thread not found, surfaced by the UI as an error creating the chat, until the app is restarted.The rollout file still exists and SQLite integrity checks remain
ok. Stripping the prefix while the app is closed is not persistent because resume/refresh writes it back. After the failed archive tears down the listener, normalizing the path again and callingthread/archivewithout reopening the thread succeeds.Besides the announced path fix, archive failure should not leave the visible thread unloaded and unusable. I can retest both behaviors when the next release is available.
Additional confirmation from the same Windows installation after attempting to clean up several affected tasks.
Environment
Observed
This confirms the failure remains reproducible on 26.814.5517.0 and that repairing individual rows does not prevent resumed tasks from re-entering the broken path form. I understand from the maintainer update above that a fix is expected in the next release.
No usernames, absolute private paths, task IDs, titles, conversation contents, credentials, raw logs, or database files are included.
Additional independent confirmation from another Windows installation on the current Store build.
Environment
26.814.5517.0Local scope and reproduction
A read-only audit of
state_5.sqlitefound:rollout_pathstarts with the Windows verbatim prefix\\?\C:\...Two unrelated completed tasks with this path form both failed through the normal
thread/archiveoperation with:For both tasks, the referenced rollout JSONL existed and was readable.
After backing up the database and rollout files, removing only the leading
\\?\from each selected row'srollout_pathallowed the normal archive operation to succeed immediately. One task remained archived. The other was later referenced/reloaded by the running Desktop app and its row was written back to the\\?\form witharchived = 0, confirming that repairing individual rows is not durable while resume/refresh can reintroduce the verbatim path.This matches the path-normalization/double-move diagnosis and confirms that build
26.814.5517.0remains affected at scale. No usernames, private paths, thread IDs, titles, conversation contents, credentials, database files, or raw logs are included.Independent confirmation on two Windows PCs, including the current
26.814.5517.0MSIX package.Primary PC:
26.814.41957OpenAI.Codex_26.814.5517.0_x64method=thread/archive, JSON-RPCerrorCode=-32603, followed by:\\?\D:\...rollout paths, while archived rows did not use the\\?\form. No SQLite rows or session files were modified.Second PC:
The new-thread and cross-machine reproduction supports a current Windows client/thread-store regression rather than a one-off path migration or a missing rollout file. No usernames, project paths, thread IDs, conversation titles/content, database files, or raw logs are included here.
Confirmed on a newer Windows Desktop build with the same deterministic sequence.
Environment:
26.814.5517.0(Microsoft Store; updater reportsNoUpdates)0.148.0-alpha.15Observed:
C:\...value inthreads.rollout_path, archive succeeds.thread/readfollowed bythread/resume.\\?\C:\....failed to archive session: thread-store internal error: failed to archive thread: The system cannot find the file specified. (os error 2)ok, directory ACLs are valid, and both path spellings resolve outside the archive flow.rollout_pathand archiving without reopening succeeds; reopening reintroduces the prefix and the failure.This also reproduces after updating from
26.814.5167.0to26.814.5517.0, so the issue appears to remain present in the current Store build available on 2026-08-20.I initially opened #39600 before finding this exact report; I am closing it as a duplicate of this issue.
Additional deterministic trigger from Codex Desktop on Windows:
thread/unarchive, the row changes from:archived = 1rollout_path = C:\Users\<user>\.codex\archived_sessions\rollout-<thread-id>.jsonlto:
archived = 0rollout_path = \\?\C:\Users\<user>\.codex\sessions\YYYY\MM\DD\rollout-<thread-id>.jsonl-32603 / os error 2.Environment:
26.814.5517.00.148.0-alpha.15This identifies
thread/unarchiveitself as another deterministic producer of the mixed Windows path representation, in addition to resume/refresh. Please includearchive -> unarchive -> archivein the Windows regression coverage for the announced fix.No usernames, private paths, thread IDs, titles, conversation content, or raw logs are included.
Independent confirmation on Windows 11.
Environment:
26.814.5517.0262000.147.0-alpha.6.6,0.148.0-alpha.9, and0.148.0-alpha.15Observed:
set_thread_archivedoperation.``
``failed to archive session: thread-store internal error:
failed to archive thread: 系統找不到指定的檔案。 (os error 2)
("The system cannot find the file specified.")
state_5.sqlite.threads.rollout_pathbegins with the Windows verbatim prefix\\?\archived=0after the failurearchived_sessions.This strongly matches the duplicate physical-path analysis in this issue: the source rollout is present, but the normal and
\\?\forms appear to be treated as separate entries before canonicalization.No rollout contents, private paths, or thread IDs are included here.
As I said above, we have a fix for this. It will be included in the next release. No need for additional confirmations or repros.
Independent confirmation with a deterministic lifecycle repro on Codex Desktop for Windows.
Reproduction
I have encountered this repeatedly: once an archived conversation is unarchived, attempting to archive it again can enter the broken state.
Local observation
For affected threads,
state_5.sqlite.threads.rollout_pathmay be persisted with the Windows verbatim prefix:The referenced
.jsonlfile still exists and is readable. After fully exiting Codex and backing upstate_5.sqlite, removing only the leading\\?\from the affectedrollout_pathallows the same thread to archive successfully without moving or deleting the rollout file.The workaround is not durable: after another archive/unarchive/resume cycle, the prefixed path can return and the failure can recur.
Expected behavior
Archive/unarchive should be repeatable indefinitely:
and equivalent Windows path representations (
C:\...vs\\?\C:\...) should not cause thread-store state divergence or duplicate filesystem operations.This adds a user-facing deterministic trigger to the existing diagnosis:
archive -> unarchive -> archivecan reproduce the problem repeatedly.