Store slug is not injective: different project paths silently share one memory/transcript directory (the ASCII case from #29471 still reproduces on 2.1.238)
Preflight Checklist
- [x] I have searched existing issues. Related prior reports are listed below; this is deliberately filed as a separate report because it covers the encoding as a whole, includes a controlled repro with a control group, and documents that a case closed as
COMPLETEDstill reproduces. - [x] This is a single bug report.
- [x] I am using the latest version of Claude Code.
What's Wrong?
The per-project storage directory under ~/.claude/projects/ is derived from the working-directory path by replacing every non-alphanumeric character with a single -. That mapping is not injective, so two different project directories can resolve to the same store — and when they do, they share auto-memory and transcripts with no warning.
The practical consequence is not a stale file on disk. MEMORY.md is loaded automatically at the start of every session, so one client's accumulated project notes are injected into an unrelated client's session context, with no user action and no indication. For contract work under NDA that is the entire problem.
Two distinct collision classes, both live on 2.1.238:
- Non-alphanumeric collapse. Every non-ASCII character becomes one
-, so only the count survives. Two Korean folder names of the same length collide completely. - Separator ambiguity.
a-banda\bboth becomea-b. This is what #29471 reported.
What Should Happen?
The store identifier should be unique per real path:
- Append a short hash of the absolute path —
<readable-slug>-<sha256[:8]>— or percent-encode instead of collapsing. Either is small and backward compatible; existing directories can be migrated, or kept readable and looked up by hash. - Independently of the encoding: record the source path inside the store (e.g.
path.json) and warn on mismatch. That alone turns a silent cross-project leak into a visible one.
Error Messages/Logs
None. That is part of the report — there is no warning, no log line, and nothing in /status. The only way I found it was by re-deriving every store from the cwd recorded inside its own transcripts.
Steps to Reproduce
A. Non-ASCII collapse (with control group)
Three fresh folders, each containing only a one-line README.md. Separate session per folder; no folder ever read another.
mkdir %TEMP%\clash\가나다 %TEMP%\clash\라마바 %TEMP%\clash\가나다라
- In
가나다: "This project's secret code is ALPHA-777. Save this to your memory." - In
라마바: "What is this project's secret code? Answer only what you know." - In
가나다라(control): same question.
| folder | non-ASCII chars | store directory | answer |
|---|---|---|---|
| %TEMP%\clash\가나다 | 3 | C--Users-USER-AppData-Local-Temp-clash---- | saved ALPHA-777 |
| %TEMP%\clash\라마바 | 3 | identical | "ALPHA-777." — returned as its own project fact |
| %TEMP%\clash\가나다라 | 4 | …-clash----- | "I don't know." |
The leaking session had never read the other folder. The memory file it picked up even carries its origin in its own front matter (description: 이 프로젝트(clash/가나다)의 비밀 코드는 ALPHA-777); the reading session still presented it as its own. The 4-character control group is the point: same parent, different length, no leak. The collision key is the count of non-alphanumeric characters.
All three sessions' .jsonl transcripts were written into those same two store directories.
B. Separator ambiguity — the #29471 case, still live
mkdir %TEMP%\clash2\ab-cd %TEMP%\clash2\ab\cd
Start a session in each, then list the stores:
%TEMP%\clash2\ab-cd -> C--Users-USER-AppData-Local-Temp-clash2-ab-cd
%TEMP%\clash2\ab\cd -> C--Users-USER-AppData-Local-Temp-clash2-ab-cd <- same store
Claude Model
Opus 5 (claude-opus-5).
Is this a regression?
Not a regression in the usual sense — the encoding has behaved this way for a long time. It is filed as a regression report in one specific sense: #29471 is marked CLOSED / COMPLETED, and the case it reported reproduces today on 2.1.238. The only activity on that issue was a duplicate-detector bot ("Found 3 possible duplicate issues … will be automatically closed as a duplicate in 3 days") followed by the lock bot. No fix shipped.
Last Working Version
N/A.
Claude Code Version
2.1.238 (Claude Code)
Platform
Windows 11 (10.0.26200), desktop app.
---
Blast radius on a working machine
I scanned all 1,085 store directories under ~/.claude/projects/ and re-derived each from the cwd recorded inside its transcripts.
(Client names below are pseudonyms. Character counts are preserved, because the character count is the thing that collides.)
- 2 stores contain more than one real project; 8 projects are affected.
- One store —
D--Project-Life-Dev-------------— is shared by six unrelated client projects: 알파산업 (12 sessions), 베타화학 (2), 감마엔텍 (1), 델타물산 (1), 시그마툴 (1), 람다철도 (1). Different customers, all four-character Korean names under the same parent. - That store holds 80 auto-memory files. Opening any one of the six loads the others'
MEMORY.mdindex as its own. - The second collision pairs 오미크론코리아 with 엡실론엔지니어 (seven characters each).
It also silently corrupts anything computed per project: my own per-project usage accounting was wrong because six projects' transcripts were pooled into one directory.
Prior reports
| issue | opened | closed | closed as |
|---|---|---|---|
| #7009 | 2025-09-02 | 2026-01-09 | NOT_PLANNED |
| #21085 | 2026-01-26 | 2026-03-01 | NOT_PLANNED |
| #29471 | 2026-02-28 | 2026-02-28 | COMPLETED (auto-closed as duplicate by bot) |
| #35162 | 2026-03-17 | 2026-04-15 | NOT_PLANNED |
| #93743 | 2026-09-11 | — | open (non-ASCII case, independent reporter) |
Five independent reporters, one encoding, no change to it. Three closed as not planned; one closed by a bot as a duplicate of issues that had been closed as not planned; all four then locked.
Documented behavior this contradicts
Each project gets its own memory directory at ~/.claude/projects/<project>/memory/.
The first 200 lines of MEMORY.md, or the first 25KB … are loaded at the start of every conversation.
Workaround — verified, but not a fix
autoMemoryDirectory in a project's .claude/settings.json does isolate memory. Verified against repro A: the colliding folder went from answering "ALPHA-777" to "I don't know," and newly saved memories landed in the pinned directory.
- It was added in 2.1.74 to let users relocate memory storage, and
CLAUDE_CODE_PROJECT_DIR_NAME(2.1.234) is documented for hosts that give each session its own config directory. Neither is presented as a remedy for this, and neither is reachable from the symptom. - It isolates memory only. Transcripts still pool in the colliding store.
Renaming folders also works, but that asks users to rename directories already referenced by shortcuts, scripts and documents, to avoid an encoding choice they cannot see.
Happy to supply the scan script, the raw store listing, or to re-run either repro on a newer build.
---
---
Looking forward to seeing this fixed soon. I want Claude to be flawless.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗