WSL resume can lower-case session cwd (/mnt/...) and make Codex switch path spelling mid-session
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:
- Start a Codex session from a mixed-case WSL path
- Verify the status bar/current cwd shows the original spelling, e.g.
/mnt/f/GH/codex - Leave that session
- Open or create another session
- Return to the original session via resume
- 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:
- Preserve case when storing session/thread
cwd
- normalize
./..lexically if needed - do not lowercase
/mnt/...paths before persistence
- Keep alias-insensitive WSL handling only at path comparison sites
- e.g. cwd matching/filtering, resume mismatch checks
- Prefer rollout
TurnContext/SessionMetaover SQLitecwdwhen 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_
6 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
@celia-oai @xl-openai
I can confirm that this issue still appears to exist in
v0.135.0under WSL.In my case, the project directory is named with mixed casing, for example:
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:
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
Harnessandharnessas 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_comparisonis 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:
Then state DB queries and path matching can use
cwd_key, while resume/runtime/sandbox logic continues to use the originalcwd.A minimal short-term fix would be to stop assigning the normalized comparison path back into
metadata.cwd/builder.cwdin 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.
This issue more than two month old. I update every week latest commits with a fixing patch https://github.com/ssh4net/codex/commit/d7cf51d3531cd46d7e6b12aa14ecaca6df26eccc
😂
Wow this still isn't fixed.
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.