anthropics / anthropics/claude-code

[BUG] Desktop app creates duplicate project directories for UNC cwd (trailing-separator normalization), causing daily chat-history loss

Offen
#89,283 6 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area:core area:desktop bug data-loss has repro platform:windows
Vorherrschende Sprache
Python
Sterne
145k
Forks
23.1k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

# Bug report

**Title:** Desktop app creates duplicate project directories for UNC cwd (trailing-separator normalization), causing daily chat-history loss and one permanently lost session transcript

---

## Environment

- Claude Code Desktop app on Windows 10 Pro (build 10.0.19045)
- App version: App version: 2.1.237
- Project working directory is a **UNC path**: `\\192.168.0.39\SpiralX_Server_V2`
- Long-running sessions, resumed daily; app typically launched ~5:00–5:20 AM

## Symptom

On two separate mornings (Aug 18 and Aug 20), logging into the app showed the **previous day's chat text gone** from the conversation view. One session's transcript was **permanently lost** (its `.jsonl` no longer exists anywhere on disk); other sessions lost only their display tail while the underlying live transcript was intact.

## What I found on disk

`%USERPROFILE%\.claude\projects\` contains **two directories for the same project**, identical except for a trailing dash (which appears to come from trailing-separator normalization of the UNC cwd):

```
--192-168-0-39-SpiralX-Server-V2 <- twin, created Aug 11 18:51
--192-168-0-39-SpiralX-Server-V2- <- original; active sessions + memory write here
```

Both contain copies of the **same session IDs**, but the twin's copies are stale and smaller:

| session file | original dir | twin dir |
|---|---|---|
| `8e732afe-…jsonl` (active session) | 27,638,049 bytes, mtime Aug 20 05:16, last line has valid timestamp | 23,882,734 bytes, mtime Aug 20 05:15, **last line truncated mid-JSON** (no timestamp parseable) |
| `d6ebb14f-…jsonl` | 97,052,241 bytes, Aug 20 05:13 | 95,498,293 bytes, Aug 17 05:11 |
| `842a1cb6-…jsonl` | 5,469,198 bytes, Aug 18 05:05 | 5,469,198 bytes, Aug 14 05:06 |

Observations:

1. Every copy's mtime falls in the **app-startup window (~05:05–05:16)** — something at launch copies/syncs transcripts between the two directories.
2. At least one copy was **interrupted mid-write** (file ends in the middle of a JSON line).
3. One session (`254a2405-…`, worked Aug 17 ~06:40–12:53) is listed by the app's session index (title, lastActivityAt, and full-text-search snippets still resolve) but its `.jsonl` exists in **neither** directory — the transcript is gone while the index remembers it.
4. Which history the UI displays appears to depend on which directory a given launch resolves — when it resolves the stale twin, everything after that copy's last sync looks deleted to the user.

## Expected

One cwd → one canonical project directory (normalize trailing separators before hashing/encoding the path); transcript writes/copies should be atomic (write-temp-then-rename) so an interrupted startup can't leave truncated files or lose a session.

## Update — Aug 24 (third occurrence + new evidence)

The history loss recurs at essentially **every app restart** (Aug 18, 20, 24). New root-cause evidence: `~/.claude.json` contains this project **registered twice** —

```
"\\\\192.168.0.39\\SpiralX_Server_V2\\" (backslash form)
"//192.168.0.39/SpiralX_Server_V2/" (forward-slash form)
```

Manually deduplicating the config does not stick: **the app re-creates the forward-slash entry within minutes of the next launch.** So some component canonicalizes the UNC cwd POSIX-style while another keeps Windows separators, and each maintains its own project directory + transcript copies — the stale one wins the display race after a restart.

## Impact

- One session transcript permanently lost (a day's working session).
- Recurring user-facing history loss every morning until we diagnosed it.
- Workaround in place: an external hourly additive backup of `projects\**\*.jsonl`.

Happy to provide directory listings or the truncated file for debugging (transcripts themselves contain internal data I'd rather not attach wholesale).

### What Should Happen?

One working directory should map to exactly one project directory under ~/.claude/projects (trailing separators in the path normalized before deriving the directory name), so chat history persists across app restarts. Transcript syncs/copies at startup should be atomic — an interrupted copy should never leave truncated .jsonl files or lose a session's transcript entirely.

### Error Messages/Logs

```shell
No error messages are produced — the loss is silent (that's part of the problem).

Evidence from disk (%USERPROFILE%\.claude\projects\), same session ID in both directories:

--192-168-0-39-SpiralX-Server-V2\8e732afe-...jsonl 23,882,734 bytes (stale copy, LAST LINE TRUNCATED MID-JSON)
--192-168-0-39-SpiralX-Server-V2-\8e732afe-...jsonl 27,638,049 bytes (live, healthy, still being written)

All copy mtimes fall in the app-startup window (~05:05-05:16 local).
One session (254a2405-...) is still listed by the app's session index
(title, lastActivityAt, search snippets all resolve) but its .jsonl no
longer exists in either directory - transcript permanently lost.

~/.claude.json contains the project registered under BOTH path spellings:
"\\\\192.168.0.39\\SpiralX_Server_V2\\"
"//192.168.0.39/SpiralX_Server_V2/"
Deleting the forward-slash duplicate does not stick - the app re-creates
it within minutes of the next launch.
```

### Steps to Reproduce

1. On Windows, open the Claude Code desktop app with a project whose working
directory is a UNC path, e.g. \\192.168.0.39\SpiralX_Server_V2
2. Work in a session; close the app.
3. Relaunch the app the next day (in our case it is typically launched each
morning) and open the same project.
4. Observe: recent chat history is missing from the conversation view -
in our case one day's tail each morning; on Aug 24 the view showed only
week-old messages.
5. Inspect %USERPROFILE%\.claude\projects\ - two directories exist for the
same project, identical names except a trailing dash. Both contain copies
of the same session .jsonl files; the twin's copies are stale/smaller and
at least one ends mid-JSON-line (interrupted copy).
6. Inspect %USERPROFILE%\.claude.json - the project appears twice, once with
backslash separators and a trailing backslash, once with forward slashes.
Remove the forward-slash entry, restart the app: it is re-created within
minutes.

Occurred on Aug 18, 20, and 24 (essentially every restart). One session's
transcript was permanently lost before we set up external backups.

### Claude Model

Other

### Is this a regression?

Yes, this worked in a previous version

### Last Working Version

_No response_

### Claude Code Version

2.1.237 (Claude Code, via the Windows desktop app)

### Platform

Anthropic API

### Operating System

Windows

### Terminal/Shell

Other

### Additional Information

Suspected root cause: one app component canonicalizes the UNC working
directory POSIX-style (forward slashes) while another keeps Windows
separators, so each maintains its own project identity - two project
directories (names differing only by a trailing dash from the trailing
separator), duplicate transcript copies synced between them at startup,
and the stale copy winning the conversation-view display after a restart.

Suggested fix: normalize path separators and trailing separators before
deriving the project directory name, and make transcript copies atomic
(write-temp-then-rename) so an interrupted startup can never truncate a
transcript or lose a session.

Impact so far: one session's transcript permanently lost; user-visible
"my chat history disappeared" every morning for a week until externally
diagnosed. Current workaround: a scheduled task syncing the twin
directories and backing up all .jsonl files every 10 minutes.

Timeline: twin directory created Aug 11 18:51; losses observed Aug 18,
20, 24 (every app restart). Happy to provide directory listings, the
truncated .jsonl (tail), or the duplicated config entries to a maintainer
on request - full transcripts contain internal data we'd prefer not to
attach wholesale.

Likely related: #87552 (same two-project-folder split and history loss on the
desktop app, triggered there by CJK/Unicode normalization). Our path is plain
ASCII - a UNC path - which suggests the root cause is broader than Unicode
normalization: the path-canonicalization layer generally (separator direction
and trailing separators). Unlike #87552 we also observe the app actively
copying transcripts between the twin folders at startup (leaving truncated
files), one permanently lost session transcript, and a duplicated
~/.claude.json project entry that regenerates after manual removal.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Rechercherichtung

Start by reproducing the UNC-path restart flow on Windows and inspect ~/.claude.json alongside %USERPROFILE%\.claude\projects\*.jsonl. Trace how the two path spellings become project identities and how startup transcript copies are performed. Done means one canonical project directory is retained and interrupted startup work cannot leave truncated or missing transcripts.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Bereich
desktop, operating-systems
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Aktiv
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.