[BUG] Past Conversations empty on Windows with mapped network drives (realpath resolves to UNC path)

Status Closed — not planned
Maintainer reply None cached
Activity 13 comments · opened Mar 13, 2026 · closed May 28, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Description

The VS Code extension's session loading silently fails when the workspace is on a mapped network drive (e.g., Z:\Claude Code). The "Past Conversations" dropdown shows only the current session — all historical sessions are missing.

Root Cause

The extension calls fs.realpath() on the workspace path, which on Windows resolves mapped drives to their UNC path:

  • Input: z:\Claude Code
  • realpath output: \\192.168.1.15\MIKE - DROPBOX\Claude Code

The sanitized UNC path (--192-168-1-15-MIKE---DROPBOX-Claude-Code) doesn't match the project directory created by the CLI (z--Claude-Code), so readdir fails with ENOENT and the error is silently swallowed.

Steps to Reproduce

  1. Map a network share to a drive letter (e.g., Z:)
  2. Open VS Code with a workspace on the mapped drive
  3. Have multiple Claude Code conversations
  4. Close and reopen VS Code
  5. Click "Past Conversations" dropdown — only the current session appears

Workaround

Create a Windows junction linking the UNC-sanitized name to the real project dir:

New-Item -ItemType Junction -Path "$HOME\.claude\projects\--192-168-1-15-MIKE---DROPBOX-Claude-Code" -Target "$HOME\.claude\projects\z--Claude-Code"


### What Should Happen?

Past Conversations should display all historical sessions regardless of 
whether the workspace is on a local drive or a mapped network drive. The 
CLI and VS Code extension should resolve the project directory name 
consistently.

### Error Messages/Logs

```shell
No visible errors — the failure is completely silent. The dropdown renders 
but shows only the current active session.

VS Code Output log (Claude VSCode channel) shows the request being sent 
but no corresponding response or error:

2026-03-13 15:13:23.106 [info] Received message from webview: {"type":"request","requestId":"177sxgvtwqi","request":{"type":"list_sessions_request"}}
2026-03-13 15:13:23.954 [info] Received message from webview: {"type":"request","requestId":"u2gpr7lwfp","request":{"type":"list_sessions_request"}}

(No list_sessions_response ever logged. Remote sessions work fine: "Fetched 2 remote sessions")

The underlying error is ENOENT on readdir for the UNC-sanitized path, 
caught and swallowed silently in the session loading code.

Steps to Reproduce

  1. Map a network share to a Windows drive letter (e.g., Z:)
  2. Open a workspace on the mapped drive in VS Code (e.g., Z:\my-project)
  3. Start a Claude Code conversation and close VS Code
  4. Reopen VS Code to the same workspace
  5. Click the "Past Conversations" dropdown — only the current session appears, historical sessions are missing

The mapped drive is key — the bug does not occur on local drives (C:\).

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

  • Claude Code extension: v2.1.75 (default model: Sonnet)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

12 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/33140
  2. https://github.com/anthropics/claude-code/issues/31219
  3. https://github.com/anthropics/claude-code/issues/33408

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

BoostlyPeter · 5 months ago

Confirmed on v2.1.76 with a mapped network drive (X: → UNC \server\share\...). Same silent failure — list_sessions returns n=0 even with 11 sessions on disk.

Root cause confirmed:

The function is IS(v) in v2.1.76 (FS(z) in v2.1.74):

async function IS(v) {
  try { return (await N3.realpath(v)).normalize("NFC") }
  catch { return v.normalize("NFC") }
}

N3 is require("fs/promises"). On Windows, fs.promises.realpath() resolves mapped drive letters to UNC paths. fs.realpathSync() (the sync variant from require("fs")) does not — it returns the drive-letter path unchanged.

Minimal fix (single line change):

// v2.1.76 — replace N3.realpath (async/promises) with b2.realpathSync (sync/fs):
async function IS(v) {
  try { return b2.realpathSync(v).normalize("NFC") }
  catch { return v.normalize("NFC") }
}

// v2.1.74:
async function FS(z) {
  try { return DH.realpathSync(z).normalize("NFC") }
  catch { return z.normalize("NFC") }
}

Both b2 and DH are require("fs") — already in scope, declared a few hundred bytes before their fs/promises counterparts.

Effect: After this change, listSessions() immediately returns the correct session count (n=11 in my case), activateSessionFromServer fires, and panel history displays correctly on restart.

The junction/symlink workaround works but requires knowing the UNC-sanitized path, which varies per machine. The one-line fix is cleaner and handles it at the source.

---

Note: this bug also breaks VS Code panel tab session restore — not just the Past Conversations dropdown. When a panel tab is restored via deserializeWebviewPanel on restart, it calls activateSessionFromServer with the saved session ID, which depends on listSessions() returning results. With n=0, the panel silently stays blank. Two separate symptoms, one root cause.

---

This is a different root cause from #33140/#31219/#33408 — those describe the ENOENT on readdir (downstream symptom); this identifies the exact IS()/FS() function and the fs/promises vs fs async behaviour difference that causes the path mismatch in the first place.

BoostlyPeter · 5 months ago

Update for v2.1.78: The function was renamed and variables changed again. New targets:

// v2.1.78 — function renamed pP, async fs = M3, sync fs = Iq:
async function pP(z) {
  try { return Iq.realpathSync(z).normalize("NFC") }
  catch { return z.normalize("NFC") }
}

Summary across versions:

| Version | Function | Async fs var | Sync fs var |
|---------|----------|-------------|-------------|
| v2.1.74 | FS(z) | o8 | DH |
| v2.1.76 | IS(v) | N3 | b2 |
| v2.1.78 | pP(z) | M3 | Iq |

All three sync vars are require("fs") — already in scope. The fix pattern is identical across versions; only the names change.

BoostlyPeter · 5 months ago

Update for v2.1.79: Only the function name changed again. All other variables identical to v2.1.78.

| Version | Function | Async fs var | Sync fs var |
|---------|----------|-------------|-------------|
| v2.1.74 | FS(z) | o8 | DH |
| v2.1.76 | IS(v) | N3 | b2 |
| v2.1.78 | pP(z) | M3 | Iq |
| v2.1.79 | hP(z) | M3 | Iq |

// v2.1.79:
async function hP(z) {
  try { return Iq.realpathSync(z).normalize("NFC") }
  catch { return z.normalize("NFC") }
}

The function has been renamed in every minor release since v2.1.76. The fix pattern is always the same — swap the async fs/promises call for the sync fs equivalent that's already in scope.

BoostlyPeter · 5 months ago

Update for v2.1.81: Multiple variable changes. Updated table:

| Version | Function | Async fs var | Sync fs var |
|---------|----------|-------------|-------------|
| v2.1.74 | FS(z) | o8 | DH |
| v2.1.76 | IS(v) | N3 | b2 |
| v2.1.78 | pP(z) | M3 | Iq |
| v2.1.79 | hP(z) | M3 | Iq |
| v2.1.81 | hP(z) | F3 | bW |

v2.1.81 kept the function name hP but changed both fs variable names (M3F3, IqbW). Confirmed patched and working across 11 user accounts (v2.1.74, v2.1.76, v2.1.81), 0 failures.

BoostlyPeter · 5 months ago

Update for v2.1.83: Function renamed again, parameter changed, both fs variables changed.

| Version | Function | Async fs var | Sync fs var |
|---------|----------|-------------|-------------|
| v2.1.74 | FS(z) | o8 | DH |
| v2.1.76 | IS(v) | N3 | b2 |
| v2.1.78 | pP(z) | M3 | Iq |
| v2.1.79 | hP(z) | M3 | Iq |
| v2.1.81 | hP(z) | F3 | bW |
| v2.1.83 | KT(K) | i1 | WN |

// v2.1.83:
async function KT(K) {
  try { return WN.realpathSync(K).normalize("NFC") }
  catch { return K.normalize("NFC") }
}

Note: v2.1.83 also changed the function parameter from z to K, and both the async and sync fs variable names changed. The function name, parameter, and fs variables have now all changed simultaneously — the only stable pattern across versions is the function signature shape and the .normalize("NFC") calls.

Confirmed patched and working on v2.1.83 across 16 user accounts (spanning v2.1.74 through v2.1.83), 0 failures.

BoostlyPeter · 5 months ago

Update for v2.1.87: Function renamed again, all variables changed.

| Version | Function | Async fs var | Sync fs var |
|---------|----------|-------------|-------------|
| v2.1.74 | FS(z) | o8 | DH |
| v2.1.76 | IS(v) | N3 | b2 |
| v2.1.78 | pP(z) | M3 | Iq |
| v2.1.79 | hP(z) | M3 | Iq |
| v2.1.81 | hP(z) | F3 | bW |
| v2.1.83 | KT(K) | i1 | WN |
| v2.1.87 | Oh(K) | w3 | uv |

// v2.1.87:
async function Oh(K) {
  try { return uv.realpathSync(K).normalize("NFC") }
  catch { return K.normalize("NFC") }
}

Seven versions tracked, bug still present and unfixed. Confirmed patched and working across 17 user accounts (v2.1.74 through v2.1.87), 0 failures.

xmutantson · 4 months ago

Still reproduces on 2.1.113 (and 2.1.112). Same root cause as described above: the extension's cwd-normalizer calls fs.realpath on Windows, which resolves mapped drives to their UNC target. The project-key hasher then produces --server-share-… while claude.exe writes to ~/.claude/projects/X--…, so the lookup never matches and listSessions returns [].

Current minified signature (identical body across versions, only symbols change):

async function <fn>(K){try{return(await <fs>.realpath(K)).normalize("NFC")}catch{return K.normalize("NFC")}}
  • 2.1.112 — named up, fs aliased as W3
  • 2.1.113 — named Gl, fs aliased as M3

One-line local patch that fixes it on both versions:

async function <fn>(K){
  if (process.platform === "win32") return K.normalize("NFC");
  try { return (await <fs>.realpath(K)).normalize("NFC") }
  catch { return K.normalize("NFC") }
}

I have a pattern-based re-apply script that matches the realpath(K)).normalize("NFC") body rather than the symbol names, so it survives version bumps. Happy to share if useful.

Filed #50170 with this info before noticing this was the canonical thread — closing that as a duplicate of this one.

3ative · 4 months ago

Also happens with directly-opened UNC workspaces, with truncation rather than empty list.
Affected path: `\\homeassistant\config` as in https://github.com/anthropics/claude-code/issues/50590

sviktor · 4 months ago

Due to this error, not only are the history entries not displayed, but the system is also looking for the memory.md file in the wrong location

github-actions[bot] · 3 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

ktremain · 2 months ago

Requesting reopen — closed by the stale-bot, not resolved; still reproduces on
extension v2.1.183.

New, actionable detail (full analysis in #63527): the realpathSync fix discussed here
and in #33140 is already in the 2.1.183 bundle, but the IDE's session list bypasses it.
There are two enumeration paths:

  • Yre({sessionStore}) -> F2e() -> Qre() = realpathSync [drive letter preserved]
  • Yre({dir}) -> KAe() -> GAe() -> OY() = await realpath [mapped drive -> UNC]

listSessions() calls Yre({dir, includeWorktrees:false}) with no sessionStore, so it takes
the async-realpath branch (OY) — the unfixed one. Fixing it is one call site: make OY use
realpathSync like Qre, or route listSessions through the sessionStore path.

Continuing the version table from the now-locked #33140:
v2.1.183 — resolver on the IDE path: OY(e) = await realpath(e); sync counterpart Qre(e)
= realpathSync(resolve(e)); sanitizer Kv (reader) / _se (writer).

New environment variant: DFS/SASE-mapped home drive (H: -> \\<corp>\dfs\...), i.e. beyond
the SMB/NAS/subst/Google Drive/OneDrive cases already on file. Active open companion: #63527.

Showing cached comments. Read the full discussion on GitHub ↗