WSL resume can lower-case session cwd (/mnt/...) and make Codex switch path spelling mid-session

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

What version of Codex CLI is running?

codex-cli 0.118.0

What subscription do you have?

Plus, Enterpise

Which model were you using?

GPT-5.4

What platform is your computer?

Windows WSL

What terminal emulator and version are you using (if applicable)?

WSL

What issue are you seeing?

Summary

On WSL-style paths such as /mnt/f/GH/codex, Codex can start with the correct path spelling and later switch to a lowercased form like /mnt/f/gh/codex, especially after resuming a session.

This affects file-oriented agent work because the active session cwd can change spelling mid-session, and the UI/model may then treat uppercase/lowercase aliases as separate-looking paths even though they resolve to the same location.

Repro

Example path:
/mnt/f/GH/codex

Observed flow:

  1. Start a Codex session from a mixed-case WSL path
  2. Verify the status bar/current cwd shows the original spelling, e.g. /mnt/f/GH/codex
  3. Leave that session
  4. Open or create another session
  5. Return to the original session via resume
  6. The resumed session can now show /mnt/f/gh/codex

I was able to reproduce this reliably with resume flows.

Expected

Codex should preserve the original cwd spelling for persisted/user-visible session state.

Case-insensitive alias handling for WSL paths is fine for comparison, but it should not rewrite the stored/displayed cwd.

Actual

A comparison-oriented WSL path normalizer lowercases /mnt/<drive>/..., and that normalized value is persisted as thread/session cwd. Later resume/fork flows can read that persisted value and apply it back to live session state.

Result:

  • session starts with original case
  • persisted metadata stores lowercase cwd
  • resume can restore lowercase cwd
  • status bar/current session path changes spelling unexpectedly

Suspected root cause

The WSL /mnt/... path comparison normalization is leaking into persisted SQLite/session metadata instead of being used only at compare sites.

That means:

  • lowercased comparison form becomes stored cwd
  • resume/fork may prefer that stored value
  • visible session state can change even if the rollout/session started with the original spelling

Proposed fix

Minimal approach:

  1. Preserve case when storing session/thread cwd
  • normalize . / .. lexically if needed
  • do not lowercase /mnt/... paths before persistence
  1. Keep alias-insensitive WSL handling only at path comparison sites
  • e.g. cwd matching/filtering, resume mismatch checks
  1. Prefer rollout TurnContext / SessionMeta over SQLite cwd when resolving resume/fork cwd
  • this also reduces impact from already-lowercased old DB rows when rollout data exists

Why this matters

This can affect every agent workflow that works with files, because the effective cwd shown and reused by the session can silently switch spelling after resume. It also causes confusing warnings like “this environment appears to expose both uppercase and lowercase aliases”.

Reference implementation

I have a working fix in my fork here:
https://github.com/ssh4net/codex/commit/a92e299245f43e3c6a9d92f4e2cdf2389f0cf73e

The patch:

  • preserves cwd case in persisted state
  • keeps WSL alias handling at comparison sites
  • avoids SQLite lowercase cwd taking priority during resume when rollout data is available

I also verified the fix manually in the real CLI by reproducing the resume flow from a mixed-case WSL path.

What steps can reproduce the bug?

Run codex in path with upper case letters, do something, create a new session, resume original session

What is the expected behavior?

Must preserve a case

Additional information

_No response_

View original on GitHub ↗

6 Comments

github-actions[bot] contributor · 3 months ago

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

  • #14257

Powered by Codex Action

qWaitCrypto · 1 month ago

@celia-oai @xl-openai
I can confirm that this issue still appears to exist in v0.135.0 under WSL.

In my case, the project directory is named with mixed casing, for example:

/mnt/.../Harness

The first Codex session starts correctly in the original path. However, after reopening/resuming the same chat/session, Codex appears to restore the cwd as the lower-cased path:

/mnt/.../harness

The files, diffs, and git state still appear to refer to the same underlying directory, which makes sense on a Windows-backed WSL mount. But this causes a serious runtime/workspace mismatch: the filesystem treats Harness and harness as the same location, while Codex sandbox/workspace/trust/permission logic can treat them as different paths. As a result, the agent may be blocked when trying to operate on files inside the project, even though it visually appears to be inside the correct workspace.

I think this has a significant impact on WSL users, because the failure mode is very confusing: the project looks correct, the file tree looks correct, and changes may appear aligned, but the runtime permission model can still reject valid operations due to the lower-cased resumed cwd.

From looking at the current code, the most fundamental fix seems to be separating the original cwd from the normalized comparison key.

In particular, normalize_for_path_comparison is appropriate for equality checks on WSL /mnt/<drive> paths, but its result should not be persisted back as the actual cwd. The actual cwd should preserve the original casing and be used for session restore, runtime configuration, sandbox roots, UI display, and workspace semantics.

A cleaner model would be something like:

cwd: PathBuf,      // original path, preserving casing
cwd_key: PathBuf,  // normalized path used only for comparison/filtering/indexing

Then state DB queries and path matching can use cwd_key, while resume/runtime/sandbox logic continues to use the original cwd.

A minimal short-term fix would be to stop assigning the normalized comparison path back into metadata.cwd / builder.cwd in the state DB path. A more robust long-term fix would be to introduce a distinct typed comparison key so that normalized paths cannot accidentally be used as real runtime cwd values.

I would really appreciate it if the Codex team could prioritize fixing this, since it makes WSL-based workflows much less reliable. I would also be happy to submit a PR for this if external contributions are currently accepted and I can be granted the necessary permission/access to do so.

ssh4net · 1 month ago

This issue more than two month old. I update every week latest commits with a fixing patch https://github.com/ssh4net/codex/commit/d7cf51d3531cd46d7e6b12aa14ecaca6df26eccc

qWaitCrypto · 1 month ago
This issue more than two month old. I update every week latest commits with a fixing patch ssh4net@d7cf51d

😂

salehrayan · 1 month ago

Wow this still isn't fixed.

ssh4net · 22 days ago

This is not a theoretical issue, it not only cost a time but tokens, because Codex itself getting this issue and react accordingly, depending on usage mode. In Goal mode it might just spent a time and usage to re-build project that switched case in a middle of process.

  The only warning still present is the existing CMake mixed-case cache path warning after build; the build exits successfully.

─ Worked for 16m 29s ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


› "CMake mixed-case cache path warning" ?


• It is only this CMake warning:

  CMakeCache.txt directory /mnt/w/visualstudio/sfm/build_u
  is different than ... /mnt/w/VisualStudio/SFM/build_u

  Cause: the build dir was configured using path casing /mnt/w/VisualStudio/SFM, but I’m running commands from /mnt/w/visualstudio/sfm. On Windows-backed mounts those resolve to the same folder, but CMake stores and compares the literal path string.

  It is not an SfM code/build failure. The binaries linked successfully.

  Clean fix is to use one path casing consistently, or recreate the build dir from the casing you want:

  rm -rf build_u
  cmake -S . -B build_u -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF
  cmake --build build_u -j 8

  No urgent need unless the warning is annoying or causes tooling confusion.


› what pwd show?


• I’ll check the shell’s current working directory directly.

• Ran pwd
  └ /mnt/w/visualstudio/sfm

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

• pwd shows:

  /mnt/w/visualstudio/sfm