[BUG] Session history empty in VSCode extension when working directory is on a mapped Windows drive

Status Open
Reported on v2.1.138
Maintainer reply None cached
Activity 9 comments · opened May 29, 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 Session history panel in the VSCode Claude Code extension shows only the current (empty) chat and no previous sessions.

Environment

  • OS: Windows 10 Pro 10.0.19045
  • Claude Code VSCode extension
  • Working directory on a mapped network drive: U:\WWW\welift.it\wwwphp8\tema

Steps to reproduce

  1. Open VSCode with a working directory on a mapped Windows drive (e.g. U:\)
  2. Start and complete one or more Claude Code sessions
  3. Click "Session history" in the Claude Code panel

Expected behavior

Previous sessions should be listed in the history panel.

Actual behavior

Only the current (empty) session is shown. No previous sessions appear.

Additional context

Session .jsonl files exist on disk at the correct path:
C:\Users\<user>\.claude\projects\u--WWW-welift-it-wwwphp8-tema\

The files are present and contain data (multiple sessions from today and previous days), so the issue appears to be in how the extension resolves or looks up the project path when the working directory uses a non-standard mapped drive letter (U:).

The sessions/ file for the active session correctly records entrypoint: "claude-vscode" and the correct cwd, so the session is being tracked — it just doesn't appear in the history UI.

Workaround: none found within the VSCode extension UI.

What Should Happen?

The Session history panel should list all previous sessions for the current project,
grouped by date (Today, Yesterday, Last 7 days, etc.), with a title or preview of
each conversation. Clicking a session should resume it with full context directly
in the VSCode panel.

The session .jsonl files already exist on disk, so the fix should ensure the
extension correctly resolves mapped Windows drive letters (e.g. U:\) when looking
up the project directory under ~/.claude/projects/.

Error Messages/Logs

Steps to Reproduce

  1. Open VSCode with a working directory on a mapped Windows drive (e.g. U:\)
  2. Start and complete one or more Claude Code sessions
  3. Click "Session history" in the Claude Code panel

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.138

Platform

AWS Bedrock

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

8 Comments

sou-i · 2 months ago

Same issue here on a different mapped drive setup.

Environment

  • Claude Code VS Code extension v2.1.162 (win32-x64)
  • Claude Code CLI v2.1.153 (native install)
  • Windows 11
  • Workspace on a NAS mounted as drive letter N: (UNC: \\10.0.4.40\work\...)

Symptom
The extension sidebar shows no past sessions when the workspace is opened via the N: drive letter, even though .jsonl files exist under ~/.claude/projects/N--.../ and claude --resume from the integrated terminal lists them all correctly.

Root cause (already identified in #31219 / #33140)
The CLI encodes the project directory from the literal drive-letter cwd (N:\...N--...), while the extension calls fs.realpath() which resolves the mapped drive to its UNC form (\\10.0.4.40\work\...) and looks up a completely different encoded directory name that doesn't exist. Write path and read path disagree.

Workaround that worked for me

  1. Open the workspace in VS Code via the UNC path (\\10.0.4.40\work\...) instead of the drive letter.
  2. Rename the existing ~/.claude/projects/N--<drive-letter-encoded>/ directory to match the UNC-derived encoded name that the extension expects.

After this, write and read encodings align and the sidebar lists sessions normally. Note that #1505 reports a separate error (ENOENT lstat on claudeVSCodeSessionsList) when opening UNC paths directly on some setups — I haven't hit that, but it's worth being aware of.

Adding this as a data point that the issue still reproduces on the latest extension version, and that #31219 (closed as not planned) describes the exact same root cause.

betta-git · 2 months ago

Confirming on a different environment (still repro on v2.1.177)

Same symptom as the OP, but a different setup — so this is not specific to the original drive letter, Windows version, or auth backend:

| | This report | OP (#63527) |
|---|---|---|
| OS | Windows 11 Home (26200) | Windows 10 Pro |
| Workspace drive | Z:\\\Qnap01\Qnap1 (QNAP NAS over SMB) | U:\ (mapped) |
| Claude Code | 2.1.177 | 2.1.138 |
| Auth backend | claude.ai subscription | AWS Bedrock |

The VS Code extension's Session history sidebar is empty, even though the session .jsonl files exist and are valid under C:\Users\<user>\.claude\projects\z--AutomatedInvestment-AutomatedInvestment\ (5 sessions, all valid JSON, all with titles).

Data layer is fine; only the sidebar UI fails:

  • The webview repeatedly sends list_sessions_request (logged in …\exthost\Anthropic.claude-code\Claude VSCode.log) but the sidebar stays empty.
  • Running claude --resume / --continue from the integrated terminal (cwd on Z:\) finds and resumes every session correctly. Verified with a forked print-mode resume — the model recalled the exact opening message of the target session. So discovery + load work via the CLI path.

Likely root cause (path resolution on network drives):
The project key is computed from the drive-letter form at write time (z--AutomatedInvestment-AutomatedInvestment), but on a mapped network drive Node's fs.realpathSync('Z:\\...') resolves to the UNC path (\\Qnap01\Qnap1\...). If the sidebar's lookup path runs the cwd through realpath (or otherwise re-encodes via UNC) while the CLI path uses the raw cwd, the sidebar ends up looking under a different (non-existent) project key and finds nothing. Note: .NET/PowerShell keep Z:\ as-is, but Node realpath expands mapped network drives to UNC — which would explain why the CLI works and the sidebar doesn't.

Workaround that works today: from the integrated terminal, claude --continue (resume latest) or claude --resume (picker). No UI fix needed for resuming; only the sidebar listing is broken.

Not fixed by deleting older coexisting extension versions (ruled that out via logs — the extension was confirmed running 2.1.177 alone when the sidebar was still empty).

BasedGPT · 2 months ago

I've been seeing this exact pattern across a few threads lately -- mapped drives, VS Code extension, sessions gone from the sidebar.

I built a toolkit for this: BasedGPT/claude-code-session-recovery. It both diagnoses the mismatch and can repair it. Run diagnose.py first -- it checks whether your project slugs under ~/.claude/projects/ are drive-letter-encoded (e.g. u--...) and emits a NOTE block when they don't match what fs.realpath() resolves. Once you've confirmed you're in the mapped-drive case, recover_vscode_sessions.py does the actual fix: it reads your .jsonl transcripts the same way the CLI does and injects them directly into VS Code's session cache (state.vscdb), bypassing the broken path lookup entirely. Close VS Code first, run it, then reopen. There's a dry-run mode if you want to see what it would change before touching anything.

One thing worth knowing before trying the directory-rename approach sou-i documented: any metadata files in %APPDATA%\Claude\claude-code-sessions\ that already have cliSessionId values pointing at the old slug will go stale after the rename. diagnose.py maps those relationships so you can see the risk upfront. recover_vscode_sessions.py sidesteps this entirely since it writes to VS Code's own cache rather than renaming project paths.

While you're waiting on an upstream fix, claude --resume from the VS Code integrated terminal (with cwd on the mapped drive) reads ~/.claude/projects/ using the raw drive letter rather than going through fs.realpath(). betta-git's comment above confirms this still works on v2.1.177.

Hope this helps, if you use my tool, would appreciate a Star :) All the best!

ktremain · 2 months ago

Added detail for v2.1.183 (win32-x64): the realpathSync fix discussed in #33140 is
already present in the bundle, but the code path the VS Code sidebar uses bypasses it.

There are two session-enumeration paths, using two different resolvers:

Yre(opts):

  • opts.sessionStore present -> F2e() -> Qre() = realpathSync(resolve(dir)) [drive letter preserved]
  • opts.sessionStore absent -> KAe() -> GAe() -> OY() = await realpath(dir) [mapped drive -> UNC]

OY(e) = await realpath(e) // async; resolves H:\... to \\<corp>\...
Qre(e) = realpathSync(resolve(e)) // sync; preserves the drive letter on Windows
// (matches @ROC2024-REAL / @BoostlyPeter's finding)

The extension calls:
listSessions() -> Yre({ dir: this.cwd, includeWorktrees: false }) // no sessionStore

...so it falls through to KAe -> GAe -> OY, i.e. the async realpath() branch. That's why
it still fails on 2.1.183 even though the realpathSync path exists in the same file. It
also explains the recurring "CLI --resume works but the IDE sidebar is empty" reports
(e.g. #45872): only the IDE enumeration path realpath-resolves; transcripts are stored
under the literal drive-letter slug.

Minimal fix (any one):

  1. Make OY use realpathSync, matching Qre (one-line parity with the working path); or
  2. Route listSessions() through the sessionStore path (F2e); or
  3. Robust: derive the project dir without realpath (match the writer, which sanitises

the literal cwd), or match transcripts by the cwd field already stored in each
.jsonl -- immune to every mapped-drive / UNC / subst variant. (The bundle already
has a UNC detector, RTe = /^[\\/]{2}/, that isn't used to guard this path.)

New environment variant: extension v2.1.183, Windows 11, workspace on a DFS/SASE-mapped
home drive (H: -> \\<corp>\dfs\home\<user>\code\MyProject). Transcripts intact under
~/.claude/projects/h--code-MyProject/; claude --resume lists them; sidebar empty; no
error logged (swallowed catch { return [] }).

(Identifiers OY/Qre/KAe/GAe/Kv are from the minified 2.1.183 build and will rename again,
per @BoostlyPeter's version table in the now-locked #33140 — but the two-path divergence
is the durable point.)

hydehung · 2 months ago

OS: Windows 11 Pro (10.0.26200)
Workspace drive: Q:\ → \\tglcifs\personal_Q$\003365 (corporate file share mapped as Q:)
Symptom: VS Code extension's Session History panel (Local tab) shows an explicit message that it can't find history because of the mapped drive path — confirming the extension is already aware of the drive-letter vs UNC resolution mismatch described above.
.jsonl transcripts are intact under C:\Users\<user>\.claude\projects\q--...\, and claude --resume from the integrated terminal lists and resumes them correctly.
Adding as another data point that this is still unresolved and affects another mapped-drive configuration (SMB share via Q:).

escherstair · 2 months ago

Root cause: VSCode extension resolves mapped network drives to UNC, but the CLI keys sessions off the drive letter

I can reproduce this reliably and traced it to the project-key derivation in the VSCode extension. The symptom: the "Session history → Local" panel is empty in VSCode, but claude --resume in the integrated terminal lists every session. It only happens when the workspace lives on a mapped network drive; the same project on a local drive (e.g. D:) works fine.

Environment

  • OS: Windows 11 (build 26200)
  • VSCode extension: anthropic.claude-code v2.1.191 (win32-x64)
  • Workspace opened from a mapped network drive: H:\Projects\MyApp, where H:\\fileserver\share$

Mechanism

The extension builds the on-disk session-folder key (in extension.js) roughly as:

// minified names in 2.1.191: FY -> vv -> Xv, with normalizer wv
key = realpath(workspacePath).replace(/[^a-zA-Z0-9]/g, "-")
// FY:  o = wv(await fs.promises.realpath(workspacePath))
// vv:  dir = join(projectsDir, Xv(o))
// Xv:  s.replace(/[^a-zA-Z0-9]/g, "-")  (+ truncate/hash if > 200 chars)
// wv:  no-op on win32 (only NFC-normalizes on darwin)

The problem is await fs.promises.realpath(...). On Windows, fs.promises.realpath (and fs.realpathSync.native) resolve a mapped network drive to its UNC target:

> await fs.promises.realpath('H:\\Projects\\MyApp')
'\\\\fileserver\\share$\\Projects\\MyApp'

(Note: the synchronous, non-native fs.realpathSync('H:\\...') keeps the drive letter — but the extension uses the promises/native path, which does not.)

So the extension looks for a project folder named from the UNC path:

~/.claude/projects/--fileserver-share--Projects-MyApp

…while the CLI keys off the literal drive-letter path and writes to:

~/.claude/projects/h--Projects-MyApp

The two folder names never match, so the extension's vv() lookup finds nothing and the Local history is empty. The sessions are never lost — they're just stored under a key the extension doesn't compute. On a local drive there is no UNC, realpath returns the path unchanged, both sides agree, and it works.

Reproduction

  1. Map a network share to a drive letter on Windows (e.g. net use H: \\fileserver\share$).
  2. Open a project from that drive in VSCode (H:\Projects\MyApp).
  3. Run a few sessions; confirm claude --resume in the terminal lists them.
  4. Open the extension's Session history → Local tab: it's empty.
  5. Inspect ~/.claude/projects: sessions are under h--Projects-MyApp (letter), but no --fileserver-share--Projects-MyApp (UNC) folder exists.

Suggested fix

Make the extension and CLI agree on the project key for mapped network drives. Options:

  • Don't realpath-resolve the workspace path before encoding the key (or fall back to the un-resolved path when realpath rewrites the drive), so both sides use the literal H:\...; or
  • When deriving the key, also probe the letter-based candidate folder (and vice-versa), instead of only the realpath-resolved one; or
  • Whatever normalization the CLI uses for the project key, have the extension apply the identical transform (single shared implementation).

Workaround (until fixed)

Create a directory junction so the UNC-derived name the extension expects points at the CLI's letter-keyed folder:

$base = "$env:USERPROFILE\.claude\projects"
New-Item -ItemType Junction `
  -Path   "$base\--fileserver-share--Projects-MyApp" `
  -Target "$base\h--Projects-MyApp"

Then reload the VSCode window. The extension reads the CLI's session files, including future ones (the junction points at the live folder). The junction must be regenerated if the share/mapping changes.

zhalker · 1 month ago

I asked Claude Fable to fix the extension and he did, faster than the developers could read this issue :)

Additionally, I created an automated process to perform the correction after each update of the Claude extension.

soandso-soandso-from-wherever-wherever · 1 month ago

Still reproduces on extension 2.1.205 (newest confirmation in this thread is 2.1.191)

Environment

  • Claude Code for VS Code: 2.1.205 (win32-x64)
  • VS Code: 1.128.0
  • OS: Windows 10 Pro 19045.6466
  • Workspace: X:\\SERVER\Share (mapped via net use)
  • CLI writing the transcripts: 2.1.183, entrypoint: "cli"; CLAUDE_CONFIG_DIR unset

@ktremain's two-path divergence is intact — only the minified identifiers moved, exactly as predicted. Under 2.1.205:

listSessions() -> wse({ dir: this.cwd, includeWorktrees: false })   // no sessionStore
               -> YWe -> JWe -> Gie -> Ly -> readdir(ENOENT) -> []

Gie(e) = try { return Cf(await so.realpath(e)) } catch { return Cf(e) }  // so = fs/promises -> UNC
xse(e) = try { r = yU.realpathSync(t) } catch { r = t }                  // writer -> drive letter preserved
Ib(e)  = wb(xse(e))

this.cwd is itself built with the sync variant at the webview construction site (realpathSync(fsPath).normalize("NFC")), and then Gie re-resolves it to UNC before wb() encodes the key — so the two halves of the same bundle disagree:

fs.realpathSync        : "X:\\example-dir\\example-sub"
fs.realpathSync.native : "\\\\SERVER\\Share\\example-dir\\example-sub"
fs.promises.realpath   : "\\\\SERVER\\Share\\example-dir\\example-sub"

key from realpathSync  : X--example-dir-example-sub              <- transcripts are WRITTEN here
key from promises      : --SERVER-Share-example-dir-example-sub  <- sidebar READS from here (ENOENT)

Worth noting for anyone reading the Node docs: fs.realpathSync (JS implementation) and fs.realpathSync.native / fs.promises.realpath (native) genuinely differ here — only the native ones resolve the drive mapping. The sync/async pair are not interchangeable on Windows mapped drives.

Narrowing this down, I transcribed the bundle's own Ay / Xie / Jie / mWe and ran them directly against the 11 real .jsonl files: 11 kept, 0 dropped once handed the correct directory. So transcript parsing, the isSidechain check, the sdk-cli/daemon entrypoint filter, and the hiddenSessionIds filter are all healthy — the defect is purely the directory lookup, and the catch {} in Ly is what turns it into a silent empty list rather than a diagnosable error.

(Related, same failure mode: when workspaceFolders is empty, the construction site falls back to os.homedir(), which yields a valid-but-wrong project key and the same silent empty list.)

@escherstair's junction workaround still works on 2.1.205, and is non-destructive — no transcripts are moved or rewritten, and new sessions appear automatically because both names resolve to one directory:

$base = "$env:USERPROFILE\.claude\projects"
New-Item -ItemType Junction `
  -Path   "$base\--SERVER-Share-example-dir-example-sub" `
  -Target "$base\X--example-dir-example-sub"

Reload the VS Code window afterwards; the sidebar only requests the session list on load. Undo with (Get-Item $path).Delete(), which removes the link and leaves the transcripts in place.

Showing cached comments. Read the full discussion on GitHub ↗