Desktop app: session history list frozen at a fixed date (2026-06-23) while new sessions keep being created

Status Closed — duplicate
Reported on v2.1.112
Maintainer reply None cached
Activity 6 comments · opened Jul 4, 2026 · closed Aug 25, 2026

Desktop app: session history list frozen at a fixed date (sessions still created, files intact)

Environment

  • Claude Desktop app version: 1.18286.0.0 (Windows 11, MSIX/Store install)
  • Claude Code CLI version: 2.1.112
  • OS: Windows 11 Home Single Language, 10.0.26200

Summary

The desktop app's session/chat history list stopped showing any session created after 2026-06-23. New sessions continue to be created and used normally, but none of them appear in the history list — it is frozen at the June 23 cutoff. The same cutoff affects the session-management tools (list_sessions / search_session_transcripts both return nothing after 2026-06-23).

Data is NOT lost

All transcript .jsonl files exist and are fully readable at:
C:\Users\udayd\.claude\projects\C--Users-udayd-OneDrive-Desktop-claude\
Files dated 2026-06-24 through today are present. This is purely a history-list / indexing display bug, not data loss.

What I verified

  • Post-June-23 transcript files are byte-for-byte the same schema as pre-June-23 files (identical top-level and message-record fields: cwd, version, message, sessionId, timestamp, etc.). So it is not a format change or corruption.
  • The cutoff is a clean date boundary (everything up to 2026-06-23 shows; nothing after), which points to an indexer/sync cursor that stalled rather than a per-file parse failure.

Steps taken that did NOT fix it

  • Fully closed and reopened the desktop app.
  • Rebooted the laptop.

Both had no effect — the list resumes from the stalled June 23 cutoff instead of rebuilding the index.

Expected

History list rebuilds from the transcript files on disk and shows all sessions, including those after 2026-06-23.

Actual

History list is permanently frozen at 2026-06-23 despite valid, newer transcript files existing on disk.

Proof - files on disk after the cutoff

Listing of transcript files modified after 2026-06-23 in
C:\Users\udayd\.claude\projects\C--Users-udayd-OneDrive-Desktop-claude\\
(none appear in the history list, yet all are valid and readable):

2026-07-05 00:16  d2a078aa-...jsonl
2026-07-05 00:11  e5d9aeab-...jsonl
2026-07-05 00:00  ff0df946-...jsonl
2026-07-04 23:48  724c6845-...jsonl
2026-07-04 23:48  794b7ccb-...jsonl
2026-07-04 23:40  4351880b-...jsonl
2026-07-04 23:38  3ba3730c-...jsonl
2026-07-04 21:12  889b9006-...jsonl
2026-07-04 12:42  38277fd3-...jsonl
2026-07-02 18:08  f27d5e95-...jsonl
2026-07-01 14:10  f27e5b1a-...jsonl
2026-06-30 17:11  5e0a4a3e-...jsonl
2026-06-30 17:04  01ef58f2-...jsonl
2026-06-30 16:58  daa0dede-...jsonl
2026-06-25 16:59  cf4a0a0d-...jsonl

The most recent session shown in the app's history list is dated 2026-06-23; every file above is newer and missing from it.

View original on GitHub ↗

5 Comments

UTKARSH698 · 1 month ago

Root cause identified

I traced this to a broken atomic file-write in the desktop app's session-index writer.

How the history list is built: The desktop app stores one metadata record per session as local_<id>.json under
%APPDATA%\Claude\claude-code-sessions\<accountId>\<orgId>\.
The Claude Code history list (and the session-management tools) are built entirely from these records, not from a live scan of the transcript .jsonl files. On startup the log shows: Loaded 26 persisted sessions from ...\claude-code-sessions\....

The bug: The app saves each record atomically by writing local_<id>.json.tmp then renaming it over the real file. Starting with build 1.18286.0.0, that write fails with EEXIST because the temp file is opened with an exclusive-create flag instead of overwriting/cleaning a stale temp:

[error] Failed to save session local_bb005772-...: EEXIST: file already exists,
open '...\claude-code-sessions\...\local_bb005772-....json.tmp'
{ errno: -4075, code: 'EEXIST', syscall: 'open', ... }
    at async Object.writeFile (node:internal/fs/promises)
    at async Rl.writeSessionToDisk (app.asar\.vite\build\index.js:3487)

Timeline (from %APPDATA%\Claude\logs\main.log):

  • Last record written successfully: 2026-06-24 00:31
  • First Failed to save session ... EEXIST error: 2026-06-24 15:53:10
  • Every session save has failed since — the same session IDs fail repeatedly (100+ times each).

Because no record can be persisted, the history list is frozen at the last successful save (2026-06-24). New sessions keep running and their transcripts are written normally by the CLI to ~/.claude/projects/**/*.jsonl (a different code path), which is why no chat data is lost.

Same faulty writer hits the config file too:

[error] Error reading or parsing config file: EEXIST: file already exists,
open '...\Claude\claude_desktop_config.json.tmp'

Why only Claude Code, not web/app chat: web chat history is server-side and never touches this local writer; only the local Claude Code index does.

Suggested fix: in writeSessionToDisk, open the temp file with truncate/overwrite semantics (or unlink any pre-existing .tmp before writing, or use a unique temp name per attempt), and clean up the .tmp on error so a single failed write doesn't permanently wedge all future saves.

Note: I reinstalled the latest version of the app and the issue still persists.

Environment: Claude Desktop 1.18286.0.0 (Windows 11, MSIX/Store), CLI 2.1.112.

UTKARSH698 · 1 month ago

Additional symptom (clearest user-facing description)

The user-visible effect of the failed writeSessionToDisk is: a session stays in the sidebar only while the app is open; as soon as the app is closed, it disappears.

This matches the root cause exactly:

  • While the app runs, the session is held in memory, so it appears in the history list and can be switched to.
  • The attempt to persist it (local_<id>.json) fails with EEXIST, so it is never written to disk.
  • On the next launch, the app loads only the records that were saved before 2026-06-24, so the newer session is gone from the list.

The underlying conversation is not lost — the transcript is written separately by the CLI to ~/.claude/projects/**/*.jsonl and remains intact; only the app-side session pointer is missing. claude --resume (which reads the transcripts directly) can still list/restore these sessions, but the desktop history UI cannot.

Net effect: since 2026-06-24, no new Claude Code session survives an app restart in the desktop history list.

UTKARSH698 · 1 month ago

Correction / refinement to my earlier root-cause comments

After going through %APPDATA%\Claude\logs\main.log (2,269 EEXIST occurrences), I need to correct one claim and sharpen two others.

Correction: this is NOT a regression introduced in build 1.18286.0.0

The same EEXIST atomic-write failure appears across six app builds in my logs, not just one:

| Build | EEXIST stack lines in main.log |
|---|---|
| 1.14271.0.0 | 694 |
| 1.15200.0.0 | 1095 |
| 1.15962.1.0 | 261 |
| 1.17377.1.0 | 508 |
| 1.17377.2.0 | 746 |
| 1.18286.0.0 | 2240 |

So it is a persistent defect across many versions, not a single-build regression. This directly explains why reinstalling the latest version did not fix it — there is no known-good recent build to reinstall to.

Sharpening: the defect is in a shared atomic-write helper, not in writeSessionToDisk alone

Every failing write funnels through the same helper (.vite/build/index.js:81writeFileopen with an exclusive-create flag → EEXIST). writeSessionToDisk is just one of at least four callers that all break identically. Distinct .tmp targets hitting EEXIST:

  • manifest.json.tmp (plugin/RPM sync) — 1,856
  • claude_desktop_config.json.tmp — 246
  • local_<sessionId>.json.tmp (the session-index records that build the history sidebar) — 200+ per session id
  • extensions-blocklist.json.tmp — 204

Because the broken code is a shared writer, a fix there repairs session history, plugin sync, config saves, and blocklist updates all at once.

Sharpening: EEXIST looks like the primary defect, but the sub-mechanism is still open

The session-index directory holds exactly 26 local_*.json records, matching the startup log Loaded 26 persisted sessions. writeSessionToDisk demonstrably fails to add new ones, which is why the sidebar is frozen and newer sessions vanish on restart. Transcripts remain intact (separate CLI write path).

One caveat I can't resolve without the source: there are currently zero leftover *.tmp files anywhere under %APPDATA%\Claude. So a simple "a stale .tmp is blocking every future write" story does not fully fit — a race on a fixed temp filename (one writer wins and cleans up, a concurrent writer hits EEXIST on exclusive-create) fits the observations better. Either way, the suggested fix stands: use a unique temp name per write (or truncate-overwrite) and clean up the .tmp on failure.

(Environment: Windows 11 Home, MSIX/Store install, package Claude_pzs8sxrjxfjjc.)

BasedGPT · 1 month ago

Your post-June-23 sessions are recoverable before any upstream fix lands. The transcripts are intact; what's missing is the metadata records the Desktop uses to build its session list. Those are two separate writes, and the EEXIST bug only broke one of them.

I built a toolkit for exactly this case: synth_session_metadata.py in BasedGPT/claude-code-session-recovery scans ~/.claude/projects/ for transcript files with no matching entry in %APPDATA%\Claude\claude-code-sessions\ and synthesises the metadata files for each one. It derives the cliSessionId, cwd, and timestamps directly from the transcript content — the same schema the Desktop would have written if the atomic save had succeeded.

Run diagnose.py from the same toolkit first. It maps all your transcript files against the metadata directory and shows the full count of orphaned transcripts before anything is written.

One path note for the MSIX install: %APPDATA%\Claude\claude-code-sessions\ can resolve to a virtualised location on a Store package. If diagnose.py returns an empty metadata directory despite the Desktop having loaded 26 sessions on startup, the real path is likely under %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude-code-sessions\ — pass that explicitly to both scripts.

After running synth_session_metadata.py, restart Desktop and the sidebar should rebuild from the newly synthesised records. Running it again periodically will catch new sessions until the upstream EEXIST fix lands.

Hope this helps, if my tools are able to help you, would appreciate a ⭐ :)

UTKARSH698 · 1 month ago

**Update: the history list can be repopulated, but the app's own broken session-save re-prunes it on restart — so new chats keep going invisible.**

Adding concrete evidence from my install (Windows 11, MSIX build 1.18286.2.0, data dir relocated to D:\Claude via a directory symlink from %APPDATA%\Claude).

The read path works. The history list is built from %APPDATA%\Claude\claude-code-sessions\<acct>\<org>\local_*.json. Mine was frozen at 6 records while ~/.claude/projects/ held 27 intact transcripts. After synthesising the missing local_*.json metadata for the orphaned transcripts, the app loaded them all — main.log:

[info] Loaded 26 persisted sessions from ...\claude-code-sessions\...

...and the full history appeared in the sidebar. So the transcripts were never lost — only the metadata index.

But it does not persist. After a normal quit/reopen the folder had degraded 26 → 9:

[info] Loaded 9 persisted sessions from ...\claude-code-sessions\...

The cause is the app's session-save failing on every write:

[error] Failed to save session local_585c186a-...: EEXIST: file already exists,
open '...\claude-code-sessions\...\local_585c186a-....json.tmp'
  at async Object.writeFile (node:internal/fs/promises:1260:14)
  at ...\app.asar\.vite\build\index.js:81:4923
  at Rl.writeSessionToDisk (...\app.asar\.vite\build\index.js:3487:5117)

Two things narrow the root cause:

  • The same file throws EEXIST repeatedly over several minutes (15:31:44, 15:32:08, 15:34:42), and there are zero .tmp files left on disk between attempts — so this is not a stale/orphaned temp file. It's a concurrency race in the shared atomic-write helper: a fixed/deterministic <target>.tmp name created with O_EXCL and no per-target serialisation, so two overlapping writes for the same target collide and the loser throws EEXIST.
  • The same helper (index.js:81:...) also throws EEXIST for claude_desktop_config.json.tmp and extensions-blocklist.json.tmp in the same startup, confirming it's a shared writer, not specific to sessions.

User impact: because saving new session metadata fails the same way, every chat created after a manual re-sync is also invisible until the folder is rebuilt again — an endless loop. Manually repopulating is not a real fix.

Suggested fix (any one is sufficient):

  • randomise the temp suffix per write (e.g. <target>.tmp.<pid>.<rand>), or
  • serialise/queue writes per target, or
  • drop the O_EXCL flag on the temp create.

The EEXIST stacks span at least 6 builds (1.14271 → 1.18286.2.0), so this is long-standing rather than a recent regression, which is why updating to the latest build doesn't help.

Showing cached comments. Read the full discussion on GitHub ↗