Skip to content

Windows App: WSL switch fails during provisioning, then hides history returned by thread/list #32902

Open

Description

@Cameloo1

Environment

  • Codex App: 26.707.62119
  • MSIX package: OpenAI.Codex_26.707.8479.0_x64
  • Codex CLI/app-server: 0.144.2
  • Windows 11 Home x64, OS 10.0.26200 build 8655
  • WSL 2.6.3.0
  • Ubuntu 26.04 LTS
  • WSL kernel 6.6.87.2-1
  • /usr/bin/bash and bubblewrap 0.11.1 present

Summary

I enabled Run Codex in WSL because native Windows sandbox execution was slow. That native sandbox behavior is already covered by #32314, #31958, and #32168.

The WSL switch exposed a separate Codex App failure:

  1. On the first WSL launch, the App repeatedly terminated the WSL app-server after approximately 90 seconds while it was still performing healthy first-run provisioning.
  2. After provisioning completed, the same app-server initialized in under one second.
  3. Codex App then displayed no existing task history, even though a direct JSON-RPC thread/list request using the App's WSL configuration returned 953 existing threads.
  4. Reverting the App to native Windows immediately restored startup and the original history.

No task data was lost.

Why WSL was enabled

This is context rather than a second bug report:

  • Native elevated mode currently takes approximately 3.5 seconds for a trivial command after workspace cleanup.
  • Simple patch operations take approximately 10-16 seconds.
  • Unelevated mode reduces a trivial command to approximately 0.2 seconds, but patching fails with:
windows unelevated restricted-token sandbox cannot enforce split writable root sets directly; refusing to run unsandboxed

The detailed native sandbox reports are already in #32314, #31958, and #32168. WSL was selected as the practical workaround.

Observed WSL behavior

First launch fails during active provisioning

After enabling Run Codex in WSL and restarting the App, the WSL app-server was terminated after approximately 90 seconds before becoming reachable.

Diagnostics showed that it was not deadlocked or crashed. It was still performing one-time setup work, including:

  • cold-starting WSL;
  • loading the approximately 298 MB executable through /mnt/c;
  • applying approximately 40 SQLite migrations; and
  • backfilling approximately 950 existing threads.

Ubuntu had approximately 13 GB of available memory. There was no OOM, segmentation fault, kernel failure, or executable failure.

This is consistent with a fixed initialization deadline treating active first-run provisioning as a hung process.

Backend initializes, but the UI hides its history

After the one-time provisioning completed, a later launch initialized the exact WSL app-server in under one second.

Codex App opened, but its task history was empty.

A direct JSON-RPC thread/list request using the same WSL CODEX_HOME, app-server flags, and request parameters returned 953 existing thread records:

  • 191 user threads
  • 618 subagent threads
  • 144 records with a null source classification

The databases and task files were present and readable. The backend returned the history, but the Desktop UI did not render it.

Persisted Windows cwd values use forms such as:

C:\Users\<user>\...

while WSL represents the same locations as:

/mnt/c/Users/<user>/...

This suggests a Desktop runtime/path/state classification problem rather than missing backend data.

Native rollback restores the App

Disabling Run Codex in WSL and restarting restored:

  • normal App startup;
  • the original task history; and
  • access to the existing projects.

The WSL-side state was preserved for diagnostics.

Reproduction steps

  1. Start Codex App in native Windows mode with existing local task history.
  2. Configure Ubuntu as the default WSL2 distribution.
  3. Verify /usr/bin/bash and bubblewrap are available.
  4. Enable Run Codex in WSL.
  5. Restart Codex App.
  6. Observe the first launch fail after approximately 90 seconds while the WSL app-server is still migrating and backfilling its state.
  7. Restart after the provisioning work has completed.
  8. Observe that the WSL app-server initializes, but the App displays no existing history.
  9. Query the same app-server directly with thread/list and observe that it returns the existing threads.
  10. Disable Run Codex in WSL and restart.
  11. Observe that native startup and the original history return.

Expected behavior

  • First-run WSL provisioning should report progress and should not be killed while migrations or backfill are advancing.
  • The initialization timeout should reset on progress, allow sufficient first-run time, or retry safely.
  • A failed WSL launch should offer an automatic rollback to native Windows.
  • Threads returned by thread/list should appear in the Desktop UI.
  • Windows and WSL cwd forms should be normalized consistently when grouping tasks under projects.
  • Switching environments must not make preserved task history appear lost.

Relationship to suggested duplicates

Diagnostic material

Sanitized App and sandbox logs can be supplied privately through /feedback. Raw SQLite databases, task JSONL files, user paths, and conversation content are intentionally not attached publicly.

Activity

  1. added
    bugSomething isn't working
    appIssues related to the Codex desktop app
    windows-osIssues related to Codex on Windows systems
    sandboxIssues related to permissions or sandboxing
    app-serverIssues involving app server protocol or interfaces
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on Jul 14, 2026
  2. changed the title [-]Windows App: elevated sandbox stalls commands; switching to WSL breaks launch and hides history[/-] [+]Windows App: WSL switch fails during provisioning, then hides history returned by thread/list[/+] on Jul 14, 2026
  3. lukassarfert commented on Jul 19, 2026

    @lukassarfert

    Adding data on this from a newer build — App 26.715.4045.0, app-server 0.145.0-alpha.18, Windows 11 Pro 26200, WSL 2.7.10.0, OracleLinux 9.5 (kernel 6.18.33.2), bubblewrap 0.6.3, roughly 393 rollout files / 547 MB of session history, 413 threads. Both failure modes @Cameloo1 reported on 26.707 / 0.144.2 are still present several builds later.

    There's an exact mechanism behind the first one, and a harder variant of the second.

    1. The provisioning kill has a permanent form: the backfill claim goes stale

    The report describes the process being killed while it was actively working. The mechanism is visible in the app-server log:

    state db backfill is running at /mnt/c/Users/<user>/.codex; waiting up to 30s before retrying startup initialization
    Error: failed to initialize sqlite state runtime under /home/<user>/.codex/sqlite:
      timed out waiting for state db backfill at /mnt/c/Users/<user>/.codex after 30s (status: running)
    

    The claim lives in backfill_state in state_5.sqlite. When a run is interrupted, that row is left at status='running' with last_success_at still NULL, and nothing expires it — there's no heartbeat or TTL. Every subsequent launch reads the row, concludes a backfill is already running elsewhere, waits its 30 seconds, and performs no work itself. The owner it waits for is long dead.

    In the original report provisioning eventually completed. Here it could not, and the app became permanently unlaunchable: main, GPU, network and storage processes all start, crashpad runs, everything reports Responding=True, but no --type=renderer process is ever spawned, so no window appears. No crash dumps, nothing in the Windows event log. From a user's perspective, clicking the icon does nothing at all, indefinitely — which makes this very hard to self-diagnose.

    Relaunching does not help and cannot: four consecutive launches moved last_watermark by zero bytes, because no launch does any work while the stale claim is held. Clearing the claim while preserving the watermark resolves it:

    UPDATE backfill_state SET status = 'pending';

    The backfill then resumed from its watermark and completed in under 40 seconds — status='complete', 413 threads, matching the Windows-side DB exactly. The next launch produced initialize_handshake_result outcome=success in 949 ms and window ready-to-show after 161 ms. Deleting the row instead also clears the lock, but discards last_watermark and forces a full rescan over /mnt/c.

    For what it's worth, the 30s value appears to be hardcoded — no CODEX_* env var, config key or CLI flag in the binary touches it. #23787 mentions a 900-second backend lease against the 30-second GUI wait, which is consistent with the behaviour here.

    2. Path normalization: UNC workspace roots break turn/start entirely

    The path-normalization theory in the report holds, and there's a sharper case than C:\... vs /mnt/c/.... With a workspace root stored as a UNC path (\\wsl.localhost\<distro>\home\<user>\src\repos\<repo>), every message submit failed:

    [Composer] submit failed  method=turn/start
    cwd="/mnt/c/Program Files/WindowsApps/OpenAI.Codex_.../app/resources/\\wsl.localhost\<distro>\home\<user>\src\repos\<repo>"
    error: Invalid request: AbsolutePathBuf deserialized without a base path
    

    A UNC path isn't absolute to the Linux app-server — absolute means a leading / — so it's treated as relative and joined onto the server's own working directory. That's what "without a base path" means here: not a notation mismatch, but a relative path with nothing to resolve it against. The consequence goes beyond hidden history: with a UNC root the app is unusable, since every message fails at turn/start.

    Rewriting the stored roots into Linux notation resolved it — active-workspace-roots, electron-saved-workspace-roots, thread-workspace-root-hints and local-projects in .codex-global-state.json, plus matching [projects.'/linux/path'] trust entries in config.toml. (The app rewrites config.toml from its own state on exit, so it has to be closed first.) Afterwards: turn/start with errorCode=null and no AbsolutePathBuf errors at all.

    Two observations that may help scope the fix:

    • The identical error was already occurring on method=fs/watch earlier the same day in native Windows mode with that UNC root open. UNC roots trip path handling in more than one code path, not only under WSL.
    • After switching, thread not found is returned for a number of older conversation IDs while those threads are present in the DB — likely the same underlying issue as the hidden-history symptom in the report, surfacing through a different call.

    Findings that look relevant but aren't

    The sandbox log fills with GetSecurityInfo failed: 1 / GetNamedSecurityInfoW failed: 1 on the WSL UNC path. These are noise — 9p doesn't implement Windows ACLs, and they appear daily including on days when everything works (305 on one entirely healthy day). Likewise bundled_executable_relocation_failed for bwrap: the bundled copy really is missing from the MSIX, but the distro's /usr/bin/bwrap is present and this is not what terminates the server. A 519 MB logs_2.sqlite is a genuine concern (#27741) but was not causal here either.

    Suggested fixes

    1. Add a TTL or heartbeat to the backfill claim. A running row whose owner no longer exists should expire rather than deadlock every future launch — this is what turns a slow first run into a permanently broken install.
    2. Reconcile the 30-second GUI wait with the backend lease, or surface backfill progress in the UI. Today a large history means the window never opens, with no user-visible reason.
    3. Translate stored workspace roots when switching to WSL mode, or normalize UNC paths server-side. Silently joining a \\wsl.localhost\ root onto the server's cwd is the worst of the available outcomes — rejecting it with a clear message would already be a large improvement.
    4. Include the offending path in the user-facing error. AbsolutePathBuf deserialized without a base path in a toast is unactionable; the log contained the answer immediately.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appapp-serverIssues involving app server protocol or interfacesbugSomething isn't workingperformancesandboxIssues related to permissions or sandboxingsessionIssues involving session (thread) management, resuming, forking, naming, archivingwindows-osIssues related to Codex on Windows systems

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions