macOS: Session history not found for paths with Unicode combining marks (NFD vs NFC)

Resolved 💬 2 comments Opened Jan 31, 2026 by gonta223 Closed Jan 31, 2026

Summary

On macOS (APFS), when a VSCode workspace path contains characters with combining marks (e.g., Japanese dakuten in 共有ドライブ), Claude Code's VSCode extension fails to load existing local session history. The same visual path in NFC (composed form) produces a different project directory key than NFD (decomposed form).

Environment

  • OS: macOS 15.4.1 (APFS)
  • VSCode Claude Code extension: 2.1.25 / 2.1.27 (native-binary)
  • Config dir: ~/claude-data (via CLAUDE_CONFIG_DIR)

Workspace Path

/Users/<me>/Library/CloudStorage/GoogleDrive-<email>/共有ドライブ/Uravation/Uravation_PARA

The key characters are ドライブ (contains dakuten on ド and ブ).

Root Cause

The project directory name is derived by t.replace(/[^a-zA-Z0-9]/g, "-") (the tm() function in extension.js).

  • macOS APFS stores paths in NFD (decomposed): = (U+30C8) + combining dakuten (U+3099)
  • VSCode provides workspace paths in NFC (composed): = U+30C9

This means the combining mark in NFD becomes an extra - in the sanitized directory name:

| Form | Sanitized directory name | Dash count |
|------|---|---|
| NFD (on disk) | ...-com----------Uravation-... | 10 dashes |
| NFC (VSCode) | ...-com--------Uravation-... | 8 dashes |

The extension looks for the NFC-derived directory, but sessions are stored under the NFD-derived directory → history appears empty.

Steps to Reproduce

  1. On macOS, open a folder in VSCode whose path contains Japanese dakuten characters (e.g., 共有ドライブ from Google Drive shared drives)
  2. Use Claude Code to create sessions (they get saved to disk)
  3. Close and reopen VSCode / start a new session
  4. Session history shows empty / "no previous sessions"

Expected Behavior

Session history should be found regardless of Unicode normalization form.

Suggested Fix

Normalize the path to a canonical form (e.g., path.normalize('NFD') on macOS, or path.normalize('NFC') consistently) before deriving the project directory name in tm().

// Before
function tm(t) {
  return join(yG(), t.replace(/[^a-zA-Z0-9]/g, "-"));
}

// After (example)
function tm(t) {
  return join(yG(), t.normalize('NFC').replace(/[^a-zA-Z0-9]/g, "-"));
}

A backward-compatible approach would also check for the legacy (NFD-derived) directory if the normalized one doesn't exist.

Workaround

Create a symlink from the NFC-derived name to the NFD-derived directory:

cd ~/claude-data/projects  # or ~/.claude/projects
ln -s "./<NFD-directory-name>" "./<NFC-directory-name>"

Additional Context

  • Only affects paths with Unicode combining marks (dakuten, handakuten, etc.)
  • Paths without combining marks (e.g., 開発, 漢字) are unaffected since NFC = NFD for those characters
  • This is a common issue on macOS with Google Drive shared drives (共有ドライブ)

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗