[BUG] Non-ASCII project path encoding causes guaranteed directory collisions and breaks --resume

Status Closed — not planned
Maintainer reply None cached
Activity 9 comments · opened Mar 30, 2026 · closed Jun 3, 2026

Summary

Claude Code's project path encoding replaces each non-ASCII character with -, creating a lossy, non-reversible mapping that causes guaranteed directory collisions between different project paths. This also breaks --resume for any external tooling that computes project directory paths.

The Problem

1. Guaranteed Directory Collisions

Claude Code encodes project paths by replacing non-ASCII characters character-by-character with -. Any two directory names with the same number of non-ASCII characters collide:

| Actual Path | Encoded Directory |
|---|---|
| ~/projects/외주/app | ...projects----app |
| ~/projects/개인/app | ...projects----app |
| ~/projects/회사/app | ...projects----app |

All three map to the exact same directory. This is not a theoretical edge case — it's a guaranteed collision for any CJK, Arabic, Cyrillic, or accented character paths of equal length.

2. Undocumented Encoding Breaks External Tooling

The encoding algorithm is not documented. Tools that need to compute the project directory path (e.g., session management scripts, WayLog, custom CLI wrappers) cannot reliably determine where Claude stores sessions.

A concrete failure case:

# External script computes path with shell: preserves Unicode
_D=~/.claude/projects/$(pwd | sed 's|/|-|g')
# Result: ...projects-외주-app  ← WHERE THE SCRIPT COPIES TO

# Claude Code internally encodes: non-ASCII replaced with -
# Result: ...projects----app    ← WHERE CLAUDE ACTUALLY LOOKS

Running claude --resume <id> fails with "No conversation found" because the session file was copied to the wrong directory.

3. Silent Session Mixing

When collisions occur, sessions from entirely different projects are stored in the same directory. While session IDs prevent data corruption, project-scoped session listings would show sessions from unrelated projects with no way to distinguish their origin.

Steps to Reproduce

Collision Demo

# Create two projects with different CJK names (same char count)
mkdir -p ~/test/외주/app ~/test/개인/app

# Start Claude in each
cd ~/test/외주/app && claude  # creates session
cd ~/test/개인/app && claude  # creates session in SAME directory

# Verify collision
ls ~/.claude/projects/ | grep test
# Only ONE directory for both projects

--resume Failure

cd ~/test/외주/app

# Compute path the way external tools would (preserving Unicode)
echo $(pwd | sed 's|/|-|g')
# ...test-외주-app  ← doesn't match Claude's internal encoding

# Copy session file to this path → claude --resume <id> fails

Why This Is Serious

| Impact | Severity | Description |
|--------|----------|-------------|
| Silent failure | Critical | No error at write time; failure only surfaces on --resume, making debugging extremely difficult |
| Tooling breakage | High | Any tool computing project paths externally will silently target the wrong directory |
| Internationalization | High | Affects ALL users with non-ASCII paths — Korean, Chinese, Japanese, Arabic, Cyrillic, accented Latin, etc. |
| Data mixing | Medium | Sessions from different projects share a directory, confusing project-scoped listings |

Suggested Fix

Option A: URL-encode non-ASCII characters (recommended)

~/projects/외주/app → ...-projects-%EC%99%B8%EC%A3%BC-app
  • Reversible, collision-free, filesystem-safe, standard (RFC 3986)

Option B: Preserve non-ASCII characters as-is

~/projects/외주/app → ...-projects-외주-app
  • Modern filesystems (APFS, ext4, NTFS) fully support Unicode directory names

Benefits of Fixing

  • Zero collisions: Every unique path maps to a unique directory
  • Predictable encoding: External tools can reliably compute project paths
  • i18n correctness: International users get the same reliability as ASCII-only users
  • Ecosystem enablement: Third-party integrations can work without reverse-engineering the encoding

Environment

  • Claude Code Version: Latest
  • Platform: macOS (APFS)
  • Path characters tested: Korean (Hangul)

Related Issues

  • #19972 — Same root cause, closed as stale. This issue provides concrete collision proof and --resume breakage evidence.
  • #36464 — UTF-8 surrogate encoding error on Windows with Korean paths
  • #18285 — Korean folder name encoding issues in Cowork

View original on GitHub ↗

9 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/35162
  2. https://github.com/anthropics/claude-code/issues/30244
  3. https://github.com/anthropics/claude-code/issues/19972

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

psh4607 · 5 months ago

Why this is not a duplicate

The suggested duplicates focus on different aspects of the same root cause:

| Issue | Focus | What's missing |
|-------|-------|----------------|
| #35162 | ASCII collision (- vs / vs _) | No non-ASCII coverage |
| #30244 | Comprehensive architecture proposal (project-local storage) | Non-ASCII collision mentioned only as a reference to #19972, no proof |
| #19972 | Non-ASCII readability loss | Collisions described as "low probability", closed as stale |

This issue provides what none of the above do:

  1. Concrete proof that non-ASCII collisions are guaranteed, not theoretical. Any two CJK/Cyrillic/Arabic directory names of equal character length produce identical encoded paths. This is demonstrated with Korean (Hangul) examples above.
  1. A specific, reproducible failure scenario (--resume breakage) — external tools computing project paths via standard shell utilities (sed, tr) produce Unicode-preserving paths that don't match Claude's internal encoding. This makes --resume fail silently with "No conversation found".
  1. All three suggested duplicates are stale or closed. #19972 is closed. #30244 is marked stale. This issue brings fresh evidence and a clear reproduction path.

I've also added a cross-reference comment on #30244 with the non-ASCII collision proof.

Yiipu · 4 months ago

PR #39148 May fix this.

wonbywondev · 4 months ago

Thanks @Yiipu for the shout-out! Quick clarification on scope so users know what to expect:

PR #39148 adds preserve-session, which mitigates this issue but does not fully solve it — the underlying slug algorithm ([^a-zA-Z0-9-]-) lives in Claude Code itself, so a proper fix (URL-encoding or Unicode preservation as suggested above) has to land in the core.

What the plugin covers for non-ASCII / Korean path users today (v1.3.0):

  • Detects slug collisionscheck_slug_collision() flags any registry entries that map to the same slug folder
  • Blocks destructive commands under collision — /fix, /copy, /move refuse to run without --force when a collision is detected
  • Diagnoses early/preserve-session:doctor shows non-ASCII path warnings + collision status per project, so users can catch the problem before it silently mixes sessions
  • NFC normalization — handles the macOS NFD ↔ Claude Code NFC mismatch (separate issue but often co-occurring with non-ASCII paths)

What it cannot solve (requires core fix):

  • Two projects like ~/외주/app and ~/개인/app still land in the same slug folder on disk — the plugin detects it, but the .jsonl files are already physically mixed by the time Claude Code writes them
  • claude --resume listing mixed sessions from multiple projects in one slug folder
  • External tools reverse-engineering the encoding

Usage today

Until the core lands a proper fix, Korean/CJK users can install the plugin as an early-warning system:

claude marketplace add https://github.com/wonbywondev/claude-plugins
claude plugin install preserve-session

Then run /preserve-session:doctor in each project to check whether you've already hit a collision. If this issue lands Option A (URL-encode) or Option B (preserve Unicode) in Claude Code core, the plugin's path_to_slug() will be updated to match.

Happy to help test any PR that tackles the core fix — I have a Korean-path test suite already set up.

wonbywondev · 4 months ago

Quick update for anyone following along — preserve-session v1.3.1 just shipped with data-safety hardening specifically for non-ASCII / CJK path users:

  • Collision-aware /preserve-session:cleanup — the --remove-with-sessions mode now skips slug folders that are still being used by an alive registered project, preventing silent data loss when two paths collide (e.g. ~/외주/app + ~/개인/app)
  • /preserve-session:doctor no longer raises false "path mismatch" alarms on Korean paths (NFC/NFD normalization fix)
  • Corrupt registry backup — if ~/.claude/project-registry.json gets corrupted, it's now backed up to .corrupt-backup.<ts> before being rewritten, instead of silently wiping all registered projects

None of this solves the root cause (still depends on this issue). But until the core lands a proper encoding fix, the plugin is now safer to leave installed for CJK users: it won't accidentally amplify the collision into actual data loss.

Same install:

claude marketplace add https://github.com/wonbywondev/claude-plugins
claude plugin install preserve-session

Run /preserve-session:doctor in each non-ASCII project once to see whether you've hit a collision.

ethan-beakmask · 4 months ago

+1 on this report. Filed an independent reproduction as #52513 before being pointed here; closing mine as duplicate in favor of this one and consolidating content here.

Also acknowledging @wonbywondev's preserve-session plugin (v1.3.1, posted last week) as a meaningful community mitigation — the collision-aware cleanup and NFC/NFD doctor check are exactly the kind of defensive workarounds that shouldn't have to exist at the plugin layer. That a third-party plugin has had to ship explicit logic for "two paths collided — don't delete the data" is, in itself, evidence that this is a correctness bug the core needs to own.

Adding three angles not yet covered in the original report that strengthen the case for prioritization:

1. Session Memory cross-project pollution

Beyond /resume listing foreign sessions, the Session Memory subsystem recalls summaries across collided directories. A user working in Project B whose path encodes to the same directory as Project A will have Claude "remember" decisions, file paths, and commitments made entirely in Project A's context. This manifests as the model confidently referring to code it never saw in the current project — a concrete, reproducible source of "hallucination" that non-English-speaking users commonly report without understanding the root cause.

2. --continue picks the wrong "last" session

claude --continue resolves to the most recently modified JSONL in the encoded directory. Under collision, this can be a foreign project's session. The user lands in what appears to be their project but with another project's conversation history loaded, with no visual warning.

3. Prior closure under weaker framing (#19972)

Issue #19972 previously raised the same underlying encoding rule, framed around readability and third-party tool integration. It was closed as not planned and marked stale, likely influenced by the original author self-characterizing collision as "theoretical, low probability." The reproductions in this issue (#40946), in #52513, and in @wonbywondev's plugin user base together make clear that collision is guaranteed and routine for monolingual non-ASCII users. Requesting consideration under a correctness framing (session isolation failure) rather than enhancement. #19972 should arguably be re-opened and linked here as superseded.

Additional reproduction data

Tested on Claude Code v2.1.108, Ubuntu, ext4, locale zh_TW.UTF-8:

/opt/Ethan_Lab/星雲資料核心   → -opt-Ethan-Lab-------
/opt/Ethan_Lab/星雲情報中枢   → -opt-Ethan-Lab-------
/opt/Ethan_Lab/성운정보핵심   → -opt-Ethan-Lab-------

Three distinct projects in two languages collapse to the same encoded directory. This complements the Korean reproduction in the original report and demonstrates that the collision domain is cross-linguistic (any two non-ASCII paths with the same ASCII skeleton and character count collide, regardless of script).

Note also that the underscore in Ethan_Lab is replaced with -, indicating the rule is strictly "non-alphanumeric → -" rather than a permissive POSIX-portable-filename rule — so even some ASCII inputs get lossy encoding.

Scope of affected users

Every Claude Code user whose project paths contain non-ASCII characters:

  • CJK markets (Taiwan, Hong Kong, mainland China, Japan, Korea)
  • Southeast Asia (Thai, Vietnamese)
  • Middle East (Arabic, Hebrew)
  • Eastern Europe (Cyrillic, Greek)
  • Any user with accented Latin characters in their path (French, German, Spanish, Portuguese, Turkish, etc.)
  • Every user with a non-ASCII username on Windows or macOS — that username appears in every project's absolute path

Related issues worth linking

  • #19972 — closed as not planned; same root cause, readability framing (should be re-opened as superseded by this issue)
  • #26964 — JSONL cross-session contamination within a project directory. This encoding bug creates that condition across unrelated projects.
  • #30244 — lossy path normalization (adjacent, distinct mechanism)
  • #6246, #36464, #40396, #14310, #38765, #31295, #51584 — broader pattern of ASCII-centric assumptions in path/string handling across the codebase.

The cluster of non-ASCII path/string bugs points to a systemic issue warranting a coordinated audit rather than per-site patches.

psh4607 · 3 months ago

Confirming this still reproduces on v2.1.126 (verified 2026-05-05)

I'm hitting this on my own machine right now. Concrete evidence from a recent session (paths anonymized):

Path I worked from: ~/projects/<2-Hangul-dir>/<proj>/<sub>
(<2-Hangul-dir> is a real directory in my project tree whose name is exactly 2 Hangul characters; the rest is just ASCII)

Where Claude Code stored the session:
~/.claude/projects/-Users-<me>-projects----<proj>-<sub>/

The 2-Hangul segment collapsed to ---- (4 dashes total: 2 from the / separators on either side + 1 per Hangul char). The session's internal cwd field correctly preserves the Hangul characters, but the directory name on disk does not — exactly the lossy mapping originally reported, unchanged in the latest version.

Additional finding worth flagging: encoding split across the ecosystem

My \~/.claude/projects/\ contains both encodings side-by-side for the same logical project:

  • \-Users-<me>-projects----<proj>-<sub>\ — lossy, written by Claude Code (active session)
  • \-Users-<me>-projects-<2-Hangul-dir>-<proj>-<sub>\ — Unicode preserved, written by a different tool in the ecosystem

So the encoding inconsistency isn't hypothetical for external tools — it's already producing split storage on real users' filesystems today. This compounds @ethan-beakmask's points about Session Memory pollution and \--continue\ selecting wrong sessions: under collision the failures are silent, but under encoding-drift across tools the same logical project gets fragmented across multiple slug folders, making session recovery non-deterministic.

Status check request

This issue is now 36 days old with \bug\ + \has repro\ + \area:core\ and no maintainer triage, while many newer \area:core\ bugs filed in April have been resolved or actively discussed in the same window. Could a maintainer take a look?

The community has already shipped a workaround plugin (@wonbywondev's \preserve-session\ v1.3.1), but as the plugin author explicitly notes, the underlying slug algorithm in core is the only proper fix — the plugin can detect collisions and prevent destructive operations, but it cannot prevent two different paths from physically mixing \.jsonl\ files in the same slug folder once Claude Code writes them.

The two suggested fixes (URL-encode non-ASCII per RFC 3986, or preserve Unicode as-is on modern filesystems) are both small, contained changes to the path-to-slug function. Happy to test any candidate PR against my Korean-path setup.

github-actions[bot] · 2 months ago

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

neo168 · 1 month ago

Still reproduces on v2.1.214 / macOS 26.5.2. Adding an impact dimension the earlier reports (all focused on --resume) didn't emphasize: the same collision also merges each project's CLAUDE.md and memory/, causing silent cross-project memory bleed.

Any four distinct projects whose names are each 4 CJK characters collapse into one folder:

~/Projects/一二三四  →  ~/.claude/projects/-Users-<user>-Projects-----
~/Projects/五六七八  →  (same)
~/Projects/甲乙丙丁  →  (same)
~/Projects/子丑寅卯  →  (same)

Consequences beyond --resume:

  • /resume in any one of them lists all four projects' sessions.
  • They share a single CLAUDE.md and memory/MEMORY.md.
  • Auto-memory saved while working on project A loads when opening project B. The memory bleed is completely silent — I only noticed because /resume surfaced sessions that obviously didn't belong.

So this is a data-isolation problem, not just a resume-lookup inconvenience: saved memories can surface in the wrong project context with no indication. Given this is labeled bug + has repro + area:core yet was closed as not planned with no maintainer comment — could it be reconsidered/reopened? Even Option B (preserve the original characters; APFS/ext4/NTFS all handle Unicode) would fix both the collision and the silent memory leakage.