[Windows] Sessions missing in Desktop app — EXDEV cross-device rename fails when projects are on different drive than AppData

Resolved 💬 3 comments Opened Mar 9, 2026 by iso2kx Closed Mar 13, 2026

Bug Description

On Windows, when projects live on a different drive (e.g., D:) than %AppData% (on C:), the Desktop app fails to persist session index files. Sessions appear missing or messages disappear after closing and reopening the app.

Root Cause

The LocalSessionManager uses fs.rename() for atomic writes (write to .json.tmp, then rename to .json). On Windows, fs.rename() fails with EXDEV: cross-device link not permitted when source and target are on different drives.

This causes session index files in %AppData%\Claude\claude-code-sessions\ to get stuck as .json.tmp — the app only reads .json files, so these sessions become invisible.

Reproduction

  1. Install Claude Desktop on Windows (AppData on C:)
  2. Create a project on a different drive (e.g., D:\Projects\my-app)
  3. Open the project in Claude Code via the Desktop app
  4. Have a few conversations
  5. Close and reopen the Desktop app
  6. Some sessions are missing from the sidebar

Logs

main.log shows repeated errors every ~10 seconds:

[error] EXDEV: cross-device link not permitted, rename
  'C:\Users\<user>\AppData\Roaming\Claude\...\manifest.json.tmp'
  -> 'C:\Users\<user>\AppData\Roaming\Claude\...\manifest.json'
[error] [LocalSessionManager] Failed to check git status: git exited with code 128:
  fatal: not a git repository

Evidence

Session index directory shows stuck .tmp files:

local_abc123.json      <-- visible to app (9 sessions)
local_def456.json.tmp  <-- INVISIBLE to app (7 sessions stuck)

Meanwhile, the actual session JSONL data in ~/.claude/projects/ is fully intact.

Suggested Fix

Replace fs.rename() with fs.copyFile() + fs.unlink() for cross-device safety:

// Before (breaks across drives)
await fs.rename(tmpPath, targetPath);

// After (works across drives)
try {
  await fs.rename(tmpPath, targetPath);
} catch (err) {
  if (err.code === 'EXDEV') {
    await fs.copyFile(tmpPath, targetPath);
    await fs.unlink(tmpPath);
  } else {
    throw err;
  }
}

Workaround

Manually copy .json.tmp files to .json in:

%AppData%\Claude\claude-code-sessions\<id>\<id>\

Environment

  • Windows 11 Home 10.0.26200
  • Claude Code CLI: 2.1.71
  • Desktop bundled: 2.1.64 (also doesn't auto-update to match CLI)
  • Projects on D: drive, AppData on C: drive

Additional Issue

The LocalSessionManager also spams git status checks every 10 seconds on non-git directories, flooding main.log with errors.

View original on GitHub ↗

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