claude-code - 💡(How to fix) Fix Project paths containing `_` end up in two `~/.claude/projects/` keys; memory and session state silently split between them on Windows [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54066Fetched 2026-04-28 06:40:08
View on GitHub
Comments
2
Participants
3
Timeline
10
Reactions
0
Timeline (top)
labeled ×6commented ×2cross-referenced ×2

Error Message

  1. If the sanitisation rule changes in a future release, refuse to silently re-key: warn and offer migration.

Fix Action

Fix / Workaround

Local workaround

Code Example

New-Item -ItemType Junction `
       -Path 'C:\Users\james\.claude\projects\C--dev-foo-bar\memory' `
       -Target 'C:\Users\james\.claude\projects\C--dev-foo_bar\memory'
RAW_BUFFERClick to expand / collapse

On Windows, a project path containing an underscore produces two parallel storage directories under ~/.claude/projects/:

  • C--dev-physics-project/ — every separator (\, /, :, _) replaced with -
  • C--dev-physics_project/ — separators replaced with -, but _ preserved

Different Claude Code subsystems write to different variants. On my machine this caused silent loss of memory (the memory/*.md files Claude Code persists per project): writes accumulated in one variant for one period and the other for another, with no warning. New sessions read from whichever key the current binary picks and behave as if there is no prior memory, even though the files still exist at the parallel key.

Reproducer

  1. On Windows: mkdir C:\dev\foo_bar (any path with _).
  2. cd C:\dev\foo_bar and start Claude Code. Have a session that writes to memory.
  3. Check ~/.claude/projects/. Both C--dev-foo-bar/ and C--dev-foo_bar/ may exist, with state split between them.

Concrete evidence on my machine

Two affected projects, both with _ in the path.

C:\dev\physics_project:

VariantMemory filesSession JSONLsNewest mtime
C--dev-physics-project/01 (today)2026-04-27
C--dev-physics_project/332 (older)2026-04-27

Session-storage keying flipped from underscore to hyphen on 2026-04-27. Memory written by older underscore-keyed sessions is invisible to today's hyphen-keyed session.

C:\dev\ml_project:

VariantMemory filesSession JSONLsNewest mtime
C--dev-ml-project/7 (newest 2026-04-22)9 (since 2026-04-14)2026-04-22
C--dev-ml_project/13 (newest 2026-04-16)02026-04-16

Sessions always went to hyphen. Memory writes shifted from underscore to hyphen around 2026-04-16. The two file sets are disjoint by name (no overlap), so half of the accumulated memory is unreachable from any given session.

Version / timing

  • claude --version: 2.1.119
  • Local claude.exe mtime: 2026-04-24 00:36:44 (matches the public 2.1.119 release)
  • autoUpdatesChannel: "latest" in global settings.json
  • ml_project memory cutover: ~2026-04-16
  • physics_project session-storage cutover: 2026-04-27

The two cutovers are on different dates and in different subsystems, so at least two distinct path-key code paths exist with inconsistent rules. Neither cutover lines up exactly with the local binary install date, so the trigger is not purely the binary version on this machine.

Related issues

  • #19910 (closed, not planned) — duplicate .claude.json entries from Windows path format inconsistency. Same root-cause class; different surface (config file vs ~/.claude/projects/).
  • #19972 — encoding rule replaces non-alphanumerics with -.
  • #27706 — Windows path normalisation duplicates.
  • #53340 — project-level folders missing in v2.1.119 sidebar; possibly the same keying flip surfacing in the UI.

The novel aspect here is silent data loss, not just config pollution: the memory/*.md files are how Claude Code persists what it has learned across sessions. When sessions read from a different key than where memory was written, the assistant behaves as if it has no prior context, and there is no user-visible signal that the files still exist at the parallel key.

Proposed fix

  1. One canonical path-key sanitisation function, used by all subsystems (sessions, memory, settings, config). Document the rule.
  2. One-time migration on first launch after the fix: detect duplicate keys for the same project (pairs differing only in _/-), merge memory and session JSONLs, report the merge to the user.
  3. If the sanitisation rule changes in a future release, refuse to silently re-key: warn and offer migration.

Local workaround

For Windows users hitting this now:

  1. Identify the canonical variant — usually whichever has the most recent / largest content (often the underscore-preserving one).
  2. Copy any missing files from the other variant into canonical. Merge MEMORY.md indexes by hand.
  3. Delete the non-canonical memory/ directory.
  4. Create a directory junction so the non-canonical path resolves to canonical:
    New-Item -ItemType Junction `
        -Path 'C:\Users\james\.claude\projects\C--dev-foo-bar\memory' `
        -Target 'C:\Users\james\.claude\projects\C--dev-foo_bar\memory'
    No admin needed (junction, not symlink). Confirm both paths resolve to the same files afterwards.

Session JSONLs can stay where they are — no race risk per file.

Environment

  • OS: Windows 11 Pro 10.0.26200
  • Shell: Git Bash and PowerShell (both observed; not the shell-format issue from #19910)
  • Claude Code: 2.1.119
  • Auto-update: enabled

Severity

High for any user with _ in a project path. Silent data loss with no user-visible warning is the failure mode.

extent analysis

TL;DR

The most likely fix for the silent data loss issue is to implement a canonical path-key sanitization function used by all subsystems and perform a one-time migration to merge duplicate keys.

Guidance

  • Identify the canonical variant of the project path by checking the most recent or largest content, often the underscore-preserving one.
  • Merge memory and session JSONLs from the non-canonical variant into the canonical one, and delete the non-canonical memory/ directory.
  • Create a directory junction to resolve the non-canonical path to the canonical one using PowerShell.
  • Consider implementing a canonical path-key sanitization function to prevent similar issues in the future.

Example

New-Item -ItemType Junction `
    -Path 'C:\Users\james\.claude\projects\C--dev-foo-bar\memory' `
    -Target 'C:\Users\james\.claude\projects\C--dev-foo_bar\memory'

This command creates a directory junction to resolve the non-canonical path to the canonical one.

Notes

The proposed fix requires a one-time migration to merge duplicate keys, and the sanitization rule should be documented to prevent similar issues in the future. The local workaround can help mitigate the issue, but a permanent fix is necessary to prevent silent data loss.

Recommendation

Apply the proposed fix by implementing a canonical path-key sanitization function and performing a one-time migration to merge duplicate keys, as it addresses the root cause of the issue and prevents silent data loss.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Project paths containing `_` end up in two `~/.claude/projects/` keys; memory and session state silently split between them on Windows [2 comments, 3 participants]