Desktop 3p Code sessions disappear from UI after restart while JSONL transcripts remain on disk

Status Fixed / completed
Maintainer reply None cached
Activity 14 comments · opened May 16, 2026 · closed Aug 25, 2026

Preflight Checklist

  • [x] I have searched existing issues and found related reports, but this case is specifically about Desktop 3p-created sessions not reappearing after restart even though their JSONL transcripts exist.
  • [x] This is a single bug report.

What's Wrong?

Claude Code Desktop 3p sessions created from the Desktop UI do not appear to persist in the Desktop Code UI after closing and restarting the app.

The underlying transcript data is not lost: valid .jsonl transcript files remain on disk and contain the expected user/assistant messages plus session metadata. However, after restarting Desktop, the previous Code sessions are not shown/restored in the Desktop UI, which makes it look like the conversation history was lost.

This appears to be a Desktop UI / session index discovery issue rather than transcript data loss.

What Should Happen?

After restarting Claude Code Desktop 3p, sessions created from the Desktop Code UI should still be visible and resumable in the Desktop UI.

If Desktop uses a separate app-side session index, it should either:

  1. persist index records for Desktop-created sessions reliably, or
  2. rebuild/adopt them from the existing JSONL transcript files on startup.

At minimum, Desktop should surface that transcript files exist on disk and provide a repair/import/resume path instead of presenting an empty or missing history state.

Steps to Reproduce

  1. On Windows, open Claude Code Desktop 3p.
  2. Start a Code session from the Desktop UI in a local project directory such as <drive>:\path\to\project.
  3. Ask questions / use the session normally.
  4. Confirm that a transcript file is written under the Claude Code projects transcript directory, e.g. <claude-code-data>\projects\<encoded-project-path>\<session-id>.jsonl.
  5. Fully close Claude Code Desktop.
  6. Reopen Claude Code Desktop and return to the Code UI for the same project.
  7. Observe that the prior session is not shown/restored in the Desktop UI, even though the JSONL transcript still exists and contains the conversation.

Local Evidence (Sanitized)

On my machine, multiple valid JSONL transcripts exist under a Claude Code project transcript directory like:

<claude-code-data>\projects\<encoded-project-path>\<session-id>.jsonl

Each transcript includes metadata similar to:

cwd: <drive>:\path\to\project
entrypoint: claude-desktop-3p
version: 2.1.x
gitBranch: <branch-name>

The transcript files contain full user/assistant messages, so the data is present on disk.

However, the Desktop 3p app-side session index directory exists but does not contain corresponding session wrapper/index files for these sessions. As a result, Desktop does not list or restore them after restart.

Why This Seems Related To Existing Reports But Distinct

There are existing issues about Desktop not showing CLI/VS Code sessions because Desktop does not adopt pre-existing JSONL transcripts.

This report is slightly different: the affected sessions were created from Claude Code Desktop 3p itself (entrypoint: claude-desktop-3p), not only from the standalone CLI or VS Code extension. Desktop writes the JSONL transcripts, but after restart the Desktop UI still does not show the sessions.

Impact

Users may believe their Claude Code Desktop conversation history was lost after restart, even though transcripts are still on disk. This is especially confusing because the data exists but the Desktop UI provides no visible recovery/import path.

Environment

  • Platform: Windows
  • Product area: Claude Code Desktop 3p / Code UI session history
  • Claude Code CLI installed: yes
  • Claude Code version family observed in transcripts: 2.1.x

Additional Information

Please avoid requiring users to move JSONL transcripts into project directories or manually edit internal session metadata. The expected behavior is that Desktop-created sessions remain visible across Desktop restarts, or that Desktop can rebuild its UI/session index from the existing transcript store.

View original on GitHub ↗

14 Comments

github-actions[bot] · 3 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/54759
  2. https://github.com/anthropics/claude-code/issues/58847
  3. https://github.com/anthropics/claude-code/issues/38691

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

jianminYa · 3 months ago

Workaround / additional diagnosis

This issue looks closely related to the same family of Desktop session-history problems reported in, for example:

  • #54759 — Sessions disappear from recent conversations on desktop app restart (Windows)
  • #58847 — Claude Code section sidebar empty on cold start; renderer reports setFocusedSession: sessionId=null despite session store loading
  • #38691 — All sessions lost after Claude Desktop update on Windows (data intact on disk)
  • #58670 — Desktop Code tab: pre-existing CLI/VS Code sessions invisible because Desktop-side local_*.json index entries are missing

The common theme is that the transcript data can still exist on disk, but the Desktop Code UI does not show the session because its Desktop-side session index is missing or incomplete.

In my Desktop 3p case, I found a more specific failure mode:

Failed to save session local_<desktop-session-id>:
EXDEV: cross-device link not permitted,
rename '<...>/local_<desktop-session-id>.json.tmp' -> '<...>/local_<desktop-session-id>.json'

So Desktop had already written a valid temporary session-index file:

local_<desktop-session-id>.json.tmp

but failed to rename it to the final file:

local_<desktop-session-id>.json

After restarting Desktop, the UI appears to ignore the .json.tmp file and only discovers sessions with the final .json index file. The underlying transcript .jsonl is still present and valid.

Temporary local workaround

As a temporary workaround, copying valid local_*.json.tmp files to local_*.json appears to restore the Desktop history entries for those sessions.

Important caveats:

  • This is not an official fix.
  • It modifies Desktop's local session-index cache, not the transcript .jsonl files.
  • It should not overwrite existing .json files.
  • It should preferably be run when Desktop is not actively generating a response.
  • It only copies files that Desktop itself already wrote as valid JSON.

A sanitized PowerShell version of the workaround:

$ErrorActionPreference = 'Stop'

$roots = @(
    (Join-Path $env:LOCALAPPDATA 'Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude-3p\claude-code-sessions'),
    (Join-Path $env:APPDATA 'Claude-3p\claude-code-sessions')
) | Select-Object -Unique

foreach ($root in $roots) {
    if (-not (Test-Path -LiteralPath $root)) {
        continue
    }

    Get-ChildItem -LiteralPath $root -Recurse -Filter 'local_*.json.tmp' -File | ForEach-Object {
        $tmpPath = $_.FullName
        $targetPath = $tmpPath -replace '\.tmp$', ''

        if (Test-Path -LiteralPath $targetPath) {
            return
        }

        # Validate that the tmp file is parseable JSON and has the expected bridge fields.
        $raw = Get-Content -LiteralPath $tmpPath -Raw -Encoding UTF8
        $parsed = $raw | ConvertFrom-Json

        if (-not $parsed.sessionId -or -not $parsed.cliSessionId) {
            return
        }

        Copy-Item -LiteralPath $tmpPath -Destination $targetPath -ErrorAction Stop
    }
}

In my local test, running this once restored recent Desktop Code history entries after restart.

Why this may help triage

This suggests that at least one root cause is not only "Desktop does not adopt existing JSONL transcripts", but also:

  1. Desktop creates a valid session-index temp file;
  2. Desktop fails to finalize it because the atomic rename throws EXDEV;
  3. Desktop does not recover from the leftover .json.tmp on next startup;
  4. the UI then behaves as if the session history is missing, even though both the transcript and the temp index are present.

A product-side fix could be one or more of:

  • avoid cross-device atomic rename for this cache path, or fall back to copy+delete on EXDEV;
  • on startup, detect valid local_*.json.tmp files and finalize/adopt them;
  • rebuild Desktop session-index entries from existing transcript .jsonl files when the index is missing;
  • show a repair/import prompt instead of silently hiding sessions.
mike161078-afk · 3 months ago

Same issue after 2.1.142 → 2.1.146 update (Windows) — with a detailed on-disk diagnostic

After the 2.1.142 → 2.1.146 auto-update, most coding sessions in the sidebar show "Session not found on disk" / "Session introuvable sur le disque" when clicked. The sidebar still lists them (titles render), but opening any of them fails. Restarting Claude Desktop does not help.

I dug into the on-disk state. The session data is not lost — the app's index simply fails to resolve it:

  1. Session metadata intact%APPDATA%\Claude\claude-code-sessions\<workspaceId>\<subId>\local_<uuid>.json — 275 files, each with valid sessionId, cliSessionId, cwd, title, timestamps.
  1. Transcripts intact%USERPROFILE%\.claude\projects\<encoded-cwd>\<cliSessionId>.jsonl — 243 files present.
  1. Transcripts sit at the EXACT path the app derives from each session's cwd. For one project I checked every session: 9/9 with a persisted transcript had the file at precisely projects\<encode(cwd)>\<cliSessionId>.jsonl (encoding: drive : and \-). Metadata ✓, transcript ✓, path ✓ — yet the UI still reports "not found".

Conclusion: not a missing-file problem. Every file the app needs exists and is correctly located. The app's internal session index does not resolve sessions despite a correct on-disk state. The regression appeared with 2.1.146.

Expected: on startup, Claude Desktop should rebuild/resolve its session index from local_<uuid>.json metadata + the transcripts under .claude\projects\, and open sessions whose files are present.

Impact: multi-project session history — a core reason to use Claude Desktop — is fully inaccessible from the UI even though all data is on disk. There is no documented way to force an index rebuild.

Requests:

  1. A way to force the app to re-scan / rebuild its session index.
  2. Fix the resolver so it picks up transcripts that exist at the expected path.
  3. Pre-release QA on session persistence across version updates.

Related: #38691.

BasedGPT · 3 months ago

This is a known gap in how the Desktop handles sessions created from its own UI — and your diagnosis is right. The transcript files are intact; what's missing is the Desktop's per-session metadata entry at %APPDATA%\Claude\claude-code-sessions\<account>\<org>\local_<uuid>.json. Without a local_*.json file pointing to a transcript, Desktop has nothing to render in the session list, even when the .jsonl is right there on disk.

The fastest confirmation: check whether %APPDATA%\Claude\claude-code-sessions\ has local_*.json entries for the sessions that vanished. If the directory is empty or only contains entries for sessions started since the last restart, that confirms the metadata wasn't persisted.

If that's the pattern, synth_session_metadata.py from claude-code-session-recovery was built for exactly this — it walks your ~\.claude\projects\ directory and synthesises metadata entries for transcript files that have no corresponding local_*.json. Full write-up at #56172.

Worth noting: there's also a "Session not found on disk" variant where the metadata is present but the cliSessionId inside it points to a transcript file that no longer exists (different failure mode, different recovery path). @mike161078-afk's comment below describes that variant.

BasedGPT · 3 months ago

Hey mike161078-afk,

What you're describing — session list rows rendering correctly but opening with "Session not found on disk" — looks like a different failure mode from the OP's. Based on my research, the metadata file (local_<uuid>.json) may be intact and the cliSessionId field populated, but the transcript file that UUID points to may no longer be on disk. If that's the case, Desktop can render the session row from the metadata, but when you open it there's nothing to load.

Before concluding the data is gone, a few things worth checking:

  1. The transcript file path itself. The cliSessionId in the metadata file holds a UUID stem. The corresponding transcript would be at ~\.claude\projects\<project-slug>\<uuid>.jsonl. Check whether that file exists — sometimes the project-slug path changes if the project folder was renamed or accessed via a junction.
  1. Any backup of ~\.claude\projects\. If you have any backup copy of that directory from before the update, the transcript files would be there as .jsonl files named by their UUID.
  1. Cloud sync. If any cloud sync service covers your home directory, there may be a version of ~\.claude\projects\ from before the update window.

The claude-code-session-recovery toolkit can confirm the exact diagnosis — it cross-references metadata files against transcript files on disk and reports which sessions have broken pointers versus missing transcripts. Write-up at #56172. If the transcript files aren't recoverable, at least that confirms it cleanly rather than leaving it ambiguous.

HeavyHuntHub · 3 months ago

Confirming on the Windows MSIX desktop app — same symptom, with on-disk root-cause evidence.
Environment

  • Windows 11, Claude desktop app (MSIX/Microsoft Store), package family Claude_pzs8sxrjxfjjc, entrypoint: claude-desktop-3p
  • Desktop app 1.9255.2.0, bundled Claude Code 2.1.149
  • (Separate npm-global claude CLI 2.1.152 is unaffected)

Symptom After an auto-update, the Code-tab session sidebar lost ~80 prior sessions and now lists only sessions created since the update. All transcripts are intact in ~/.claude/projects/…/*.jsonl (full history), and both the CLI (claude --resumeCtrl+A) and the VS Code extension list/open every one by reading the folder directly. So it's purely a Desktop UI session-index issue, exactly as described.
Likely root cause (found on disk) The registry at %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\git-worktrees.json was reset during the update to:

{ "worktrees": {}, "schemaVersion": 2 }

A migration to schemaVersion: 2 appears to have dropped all existing worktree entries. Since the desktop app creates a worktree per session, emptying this registry removed those sessions from the sidebar. The claude-code-sessions index alongside it only contains the current session.
What does NOT recover them (so it's index-side, not a filter): full app restart, all session filters set to "All", Group-by → None, and the per-project filter — none surface the pre-update sessions.
Repro

  1. Use the desktop app heavily over several days (each session auto-creates a worktree)
  2. Let the app auto-update
  3. Reopen the Code tab → only post-update sessions show; the rest are gone from the UI (but present on disk)

Requested fix (seconding OP): on startup/migration, rebuild/adopt the session index from the existing ~/.claude/projects JSONL transcripts, and/or add a "rescan sessions" action. As-is it reads as total session-history loss.

renatonapel-arch · 3 months ago

Another occurrence, same symptom, different angle — adding here instead of opening a duplicate. _Edited: identifiers redacted; technical content preserved._

Environment

  • Claude Code (CLI): 2.1.87
  • Platform: Windows
  • Surface: Cowork desktop / "Recent sessions" panel (not VSCode)

This case

  • Session title: <internal-project-A>
  • sessionId: <sessionId-A>
  • cwd: C:\Users\<user>\<repo>\.claude\worktrees\<wt-id>
  • branch: claude/<wt-id>
  • Transcript .jsonl: ~2 MB; last write 2026-06-01T20:28 UTC
  • Session not returned by mcp__ccd_session_mgmt__list_sessions with limit=200, include_archived=true (full inventory pulled and grepped — confirmed absent)
  • Other contemporary sessions (newer activity) appear normally → not a list-size truncation

Important deviation from the original report
This is not only post-restart: the session was still actively rotating its .jsonl (writes minutes before disappearance was noticed) while already gone from the UI. So the desync can happen while the app is running, not only across restarts.

Recurrence for the same user (3 days apart)

  • 2026-05-30: <internal-project-B> (separate sessionId / worktree) — same symptom.
  • 2026-06-01: <internal-project-A> above.

\claude --resume <sessionId>\ does NOT reindex the panel
Tested during the May 30 incident — relaunching the session via CLI brought the conversation back into a terminal, but the desktop panel still did not list it. Whatever maintains the panel index is not driven by \.jsonl\ activity alone.

Workaround that works
Read the orphaned \.jsonl\ directly, summarize state, continue work in a new session.

Happy to share \.jsonl\ excerpts privately or run any diagnostic if helpful.

Colinator01 · 3 months ago

Same symptom, different trigger — adding here instead of opening a duplicate.

The OP's sessions disappear after a restart while the .jsonl files remain intact. My case is the same end state, but caused by a winget uninstall + reinstall on Windows 11 Build 26200.7922. The reinstall was necessary because the standard ClaudeSetup.exe installer silently fails on this build, and the MSIX sideload workaround produces an app that Windows Search won't index. After the clean reinstall via winget, the sidebar is empty despite two valid .jsonl session files (273 KB and 210 KB) sitting in the correct project directory. Selecting the project folder via the project selector does not restore them, and copying the files into ~/.claude/sessions/ also had no effect.

Environment:

OS: Windows 11, Build 26200.7922
Claude Desktop version: 1.9659.2 (installed via winget install Anthropic.Claude)

How I got here:

The standard ClaudeSetup.exe from claude.com silently fails to install on my build — no error, no app, just the Setup.exe left behind. Followed the MSIX sideload workaround (https://claude.ai/api/desktop/win32/x64/msix/latest/redirect), but the sideloaded app doesn't appear in Windows Search. To fix the search issue, I did a clean winget uninstall + winget install cycle.

What happened:

After the reinstall, the Code tab sidebar is completely empty. However, two substantial .jsonl files survived in the correct project directory. Confirmed via Get-Content that these files contain valid session data — full conversation transcripts are present. The project folder still exists on disk. The .claude\sessions\ directory is empty.

What didn't work:

Fully closing and reopening Claude
Selecting the project folder via the project selector in the Code tab
Copying the .jsonl files into C:\Users\USER\.claude\sessions\

The sidebar remains empty in all cases. Account-level stats (96 messages, 174.6k tokens) load correctly from the server, confirming auth is fine — only the local session index is broken.

What would fix this:

The app should be able to rebuild its session index by scanning the existing .jsonl files in the project directory on startup, rather than presenting a permanently empty sidebar when the index is missing.

BasedGPT · 2 months ago

Hey Colinator01,

When I’ve had this exact end state (transcripts in ~/.claude/projects/ intact, sidebar empty after a reinstall), the gap was %APPDATA%\Claude\claude-code-sessions\ being cleared by the uninstall. That’s the Desktop’s per-session metadata index, separate from the transcript files and from ~/.claude/sessions/ (which is just ephemeral PID files during active sessions, not the persistent index).

I built a toolkit for this: synth_session_metadata.py in claude-code-session-recovery. It walks ~/.claude/projects/, reads each .jsonl, and synthesises the missing local_*.json entries. Worth running diagnose.py first: it maps both directories and shows you which transcripts are missing metadata before writing anything. After synth_session_metadata.py runs, restart Desktop and those two sessions should appear in the sidebar.

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

BasedGPT · 2 months ago

Hey renatonapel-arch,

The part that stands out here is it happening while the session was still running. The transcript was alive (claude --resume reached it), so the underlying data wasn’t lost — the Desktop panel just stopped indexing it.

Worktree cwd is the unusual factor. When cwd is inside <repo>\.claude\worktrees\<wt-id>, the project slug ends up embedding .claude in the middle of the path. The Desktop indexer may write a metadata entry under that slug on session start, then something during the session causes it to drop from the panel before close.

I built a toolkit for diagnosing this: diagnose.py in claude-code-session-recovery maps %APPDATA%\Claude\claude-code-sessions\ against ~/.claude/projects/ and shows whether a metadata entry exists for that worktree slug. Running it after the next recurrence would confirm whether the entry was created and then cleared, or never written at all; that’s the deciding factor for whether synth_session_metadata.py or a Desktop restart is the right fix.

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

jgabriel98 · 2 months ago

same issue happening here.
If i restart the desktop app, all history is gone from UI (but still stored on disk)

Tblaze · 2 months ago

Bug report — Claude Desktop (Cowork + Code): session/project lists never populate; root cause is the sessions/watch resume loop
Platform: macOS · App: Claude 1.15962.1 (1e236d), build 2026-06-26 (latest) · web bundle 7a099294dd

Why this report is worth prioritizing

Many existing reports describe the symptom (desktop sidebar empty; sessions/projects on disk but not shown) but
not the cause. This report includes the actual failing network call and the client code path that breaks the
sidebar — a concrete, fixable root cause — plus proof that no data was lost. It should let an engineer reproduce
and fix the underlying issue rather than re-triaging the symptom.

This is the same class of bug already filed (and acknowledged by Support) — see "Related, already-open issues" below.

Symptoms

On a clean, latest, fully-signed-in desktop app:

  • Projects section of the sidebar: empty (0) — though the same account's projects render fine in the browser.
  • Cowork chats shown: 17 (all chat type) vs 84 session records on disk; the 66 scheduled + 1 dispatch sessions and all project-space grouping are absent.
  • Code sessions shown: 8 vs 75 transcript sessions on disk (~/.claude/projects).
  • Regular cloud chats sync and display normally — only the Cowork/Code session lists and Projects are affected.

Root cause (from the renderer DevTools console)

The session lists are populated by an SSE stream:
GET https://claude.ai/v1/code/sessions/watch?exclude_tags=- Accept: text/event-stream

Observed responses (status visibly changing over ~1 hour, indicating server-side flux):

410 (Gone) → client logs "sessions/watch 410 resume_token expired"
400 (Bad Request) → client logs "sessions/watch 400 without resume_token available"

Client handler (minified, paraphrased):

jsonopen(t){
if(!t.ok){
if(t.status===410) return o=true, a&&(e.streamPosition=void 0), c(),
reject("sessions/watch 410 resume_token expired");
if(t.status===400 && !s) return c(),
reject("sessions/watch 400 without resume_token available");
}
}

The stored streamPosition (resume cursor) expires → 410; the client clears it and retries without a token →
400; it cannot bootstrap a fresh stream → retry loop (telemetry claudeai.television.sessions_watch.retry_loop
after 5 failures). Because the watch never connects, no added events arrive and the sidebar stays empty.
Corroborating: repeated MaxListenersExceededWarning for ...LocalAgentModeSessions...sessionsBridgeStatus...
(re-subscription loop), and GET /v1/toolbox/shttp/mcp/<id> 405.

These are semantic server responses (the request reaches the server and is understood), so it is not a
client network/VPN/proxy problem — it is the watch resume protocol failing to recover after cursor expiry.

Related, already-open / acknowledged issues (same class)

  • #59736 — Desktop Code sessions disappear from UI after restart while JSONL transcripts remain on disk (open, area:desktop/bug). Asks for an index rebuild from on-disk transcripts.
  • #58627 — macOS: projects not showing in desktop sidebar despite same account working in browser; sign-out/in doesn't help.
  • #45076 — macOS Cowork: session history + project metadata lost; Support classified this as a "current Cowork limitation" where session history "is not guaranteed to persist," and confirmed Cowork sessions don't sync to the web.
  • #33130 — Desktop chats lost after restart; reporter notes data is "still in LevelDB but the UI fails to render."
  • #29373 — Update migrated the store local-agent-mode-sessions → claude-code-sessions without carrying sessions over (both dirs are present on my disk).

Data integrity — nothing is lost

All of the following are present and valid on disk (every relevant JSON parses cleanly; a full pre-incident backup also exists):

local-agent-mode-sessions/<ws>/<proj>/ — 84 cowork session .json + working folders; project spaces intact under spaces/ (with populated memory/); .project-cache/*/metadata.json valid.
claude-code-sessions/.json (8) and ~/.claude/projects/*/*.jsonl (75 transcripts).

What does NOT fix it (verified by hand)

Latest app · cleared Cache/Code Cache/Service Worker · restored full IndexedDB from backup · disabled VPN ·
full sign-out/in · validated all index/config JSON. None changed the result. (Consistent with other reporters:
restart and re-login do not restore the lists.)

⚠️ Please stop recommending destructive resets

In #45076, Support advised rm ~/.claude.json + rm -rf ~/.claude/. In my case, a similar "recovery" procedure
(run by an assistant) deleted ~/Library/Application Support/Claude — destroying app state and causing the
orphaned-session condition, with no recovery path. These resets lose data without fixing the UI. Please remove
this from support playbooks and never recommend it for this symptom.

Requested fixes

  1. Server: allow sessions/watch to accept an initial connect without a resume_token (return a fresh snapshot + new cursor) instead of 400; and/or stop returning a 410 the client can't recover from.
  2. Client: on 410 expired / 400 without resume_token, fall back to a clean full re-snapshot (drop last-event-id + resume_token) instead of looping.
  3. Product: add a "rebuild session index from on-disk transcripts/spaces" repair path (requested in #59736) so users whose index is reset can recover without engineering help.
  4. Docs: if Cowork session persistence is best-effort during the research preview, state it prominently before users invest context.

Steps to reproduce

  1. Open the latest desktop app, signed in, with existing Cowork/Code sessions on disk.
  2. Observe empty Projects + partial Cowork/Code lists.
  3. DevTools → Console: GET /v1/code/sessions/watch?exclude_tags=- returns 410 then 400 in a retry loop; lists never populate.
chlwoomin · 1 month ago

Another data point (macOS, resolved): a single local_*.json index entry with null timestamps blanks the ENTIRE Code session sidebar — with zero errors logged

Environment: macOS (Darwin 25.5), Claude desktop 1.20186.0, bundled Claude Code 2.1.205

Symptom: Same end state as the OP — after every restart the Code session sidebar was completely empty, while on the very same launch main.log reported Loaded 34 persisted sessions from .../claude-code-sessions/<account>/<org> and the ccd_session_mgmt list_sessions MCP API returned every session. Transcripts in ~/.claude/projects/ were all intact. So: disk ✓, main process ✓, session API ✓, renderer list ✗.

What did NOT fix it (each attempted with the app fully quit and residual processes verified dead first):

  • Deleting IndexedDB + Session Storage
  • Moving all web storage out (Local Storage, WebStorage, blob_storage, Session Storage, IndexedDB, Cache, Code Cache, GPUCache) — the app recreated everything fresh; sidebar still blank on a 100% clean renderer state
  • Quarantining unrelated transcript directories in ~/.claude/projects/

Root cause (confirmed by the fix): Auditing the 34 index files in ~/Library/Application Support/Claude/claude-code-sessions/<account>/<org>/, exactly two were malformed:

  1. one entry with "createdAt": null, "lastActivityAt": null, "lastFocusedAt": null (and a degenerate auto title)
  2. one entry duplicating another file's cliSessionId (two index files → same transcript)

Moving just those two files out of the directory and restarting immediately restored the full sidebar.

(Honest caveat: these two entries were not written by the app — they were synthesized by an earlier session-import attempt on this machine. But the client fragility is the actionable part.)

Why this matters for this issue:

  1. One bad record silently kills the whole list. No renderer error, no skipped-entry warning; main happily logs Loaded 34 persisted sessions. Presumably the list sort/format throws on the null timestamps and the component renders empty. Suggested fix: validate index entries on load, skip+log malformed ones instead of failing the entire list.
  2. A cheap diagnostic for anyone landing here: before any destructive reset, inspect claude-code-sessions/<account>/<org>/local_*.json for entries with null timestamps or duplicate cliSessionId, and quarantine those first. In my case every cache/storage reset was useless because the problem was index data, not renderer state — consistent with upthread reports that resets never fix this class of symptom (and can destroy data).
JAESUNG826 · 1 month ago

Another data point: onQuitCleanup hits a fixed maxtimeout and aborts before all sessions' resume state is saved

Environment: Windows 11, Claude desktop 1.20186.1.0 (also reproduced on 1.20186.0.0), bundled Claude Code 2.1.205.

Symptom: Same end state as OP — after a restart, one or more Code sessions in the sidebar show "Session not found on disk" (only Archive/Delete offered), while their .jsonl transcripts under claude-code-config-stable/projects/<encoded-path>/ remain fully intact and valid (verified byte-for-byte: last line is well-formed JSON, file ends with a trailing newline, no truncation).

I hit this general symptom (transcript intact, resume link broken) 6 times over 3 days, mostly via the machine rebooting while sessions were left open — those runs show the child Claude Code process exiting with 1073807364 (a Windows forced-termination code), which is a distinct, more obviously-forceful failure path.

New evidence — on the most recent occurrence, the app was quit deliberately (not force-killed by a reboot), and it still broke. main.log for that quitting run shows:

[info] Successfully run onQuitCleanup: local-session-stop-all
...(a few seconds of unrelated cleanup: remote plugin sync, event-queue flush)...
[warn] onQuitCleanup reached maxtimeout, aborting cleanups and quitting
[info] Successully ran all onQuitCleanup handlers, marking readyForQuit
[info] beforeQuit: handler fired, going down
[info] willQuit: handler fired, going down

local-session-stop-all itself completes successfully and both affected sessions' query iterator completed cleanly — so process termination is graceful, not a forced kill. But there is a fixed overall timeout on the onQuitCleanup phase (roughly ~75–90s from the first cleanup step in my logs), and once it's hit, whatever cleanup tasks haven't run yet are simply dropped. If a per-session "save resume/cliSessionId index" step runs after local-session-stop-all (as a separate task) and hasn't executed yet when the timeout fires, that session is left with a stale/missing resume pointer even though its transcript was flushed correctly.

On the next launch, that specific session logs:

[info] [CCD] clearStaleResumeHandle session=local_<uuid> reason=getTranscript_empty dropping cliSessionId=<uuid> unarchivedCliSessionId=undefined

...even though the .jsonl for that cliSessionId is present and non-empty on disk. Meanwhile a sibling session that was open in the same window at quit time comes back with warmed successfully and no resume issue at all — so this isn't "all sessions broken", it's whichever session's index-save task didn't get a turn before the timeout (order/timing dependent, not consistently reproducible per-session).

This happened even on a deliberate, non-forced app quit — i.e. this is not purely a "Windows killed the process mid-flight" issue (which is a separate, also-real failure mode I hit earlier with the same end symptom, via exit code 1073807364 when a reboot force-kills the process directly). Both paths land on the same "session not found on disk" UI state, but the quit-with-time-to-clean-up path shown above seems like a pure ordering/timeout bug in onQuitCleanup, independent of whether the app got force-killed at all.

Workaround found (no data loss, no manual file surgery needed): using the send_message-to-another-session capability (exposed via the ccd_session_mgmt MCP tool bundled with Claude Code) against the "not found" session causes the desktop app to log sendMessage on uninitialized session; cold-starting via startSession, which re-resumes the session from its still-intact transcript (confirmed via cache_hit=true and full prior context present) and re-establishes a working cliSessionId mapping. This suggests the app can successfully rebuild the resume link from the on-disk transcript when asked to — it just isn't triggered automatically when the sidebar shows "Session not found on disk" (only Archive/Delete are offered there).

Suggested fixes, in rough priority order:

  1. Make the per-session resume-index/cliSessionId save step run (or complete) before lower-priority cleanup (remote plugin sync, etc.) in onQuitCleanup, or give it its own guaranteed time budget so it isn't the one dropped when the overall timeout fires.
  2. When the sidebar shows "Session not found on disk" but a valid transcript exists at the last-known cliSessionId (or can be found by scanning the project's transcript directory), offer a "Reconnect" action in the UI that does what the send_message cold-start path above already does internally — instead of only Archive/Delete.
  3. Log a warning (not just [warn] onQuitCleanup reached maxtimeout) naming which cleanup tasks were dropped, to make this class of bug diagnosable without needing debug-log archaeology.

Happy to provide the full (locally-sanitized) log excerpts around this occurrence, or timestamps for the other 5, if useful.