[BUG] ~20 sessions lost, only 11 survived - 2 months of work I paid for - gone
Preflight Checklist
- [x] I have searched existing issues 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?
Needed to dip into older code session conversation to check something, all I see "Session not found on disk".
- ~20 sessions lost, only 11 survived
- Session entries still show in the sidebar with titles and dates — but no transcript data behind them
- No warning, no notification, no opt-in
- Other users are reporting the same thing (google search)
Same computer, same app (I use desktop app on OSX), only recent session conversations are there, but most are gone. I PAID for this time, conversations, this discovery, why has it been silently deleted?
What Should Happen?
Sessions are stored locally, I should be able to decide if I want to archive or delete anything. It is not ethical to remove what was paid for.
Error Messages/Logs
Steps to Reproduce
Look for old sessions in code, are they there? conversations or empty session?
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude Code version 2.1.76.
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
<img width="366" height="155" alt="Image" src="https://github.com/user-attachments/assets/5457ea20-1fb7-4ef2-9c41-17188eeeb679" />
15 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Losing 20 of 31 sessions silently with no warning is awful, and the "paid for this" framing is exactly right — session transcripts are work product, and silent deletion of work product is qualitatively different from any cache eviction or storage cleanup that the user would normally accept. I'm sorry you're dealing with this.
A few practical notes that may or may not apply to your situation, then the structural observation.
Where session data actually lives on macOS
Claude Code (CLI) writes session transcripts under
~/.claude/projects/<encoded-working-directory>/. The encoding replaces/with-. Each session is a.jsonlfile withcliSessionIdin the filename. The sidebar titles you're seeing come from a separate index file that retains metadata even after the underlying.jsonlis removed — which is the exact mismatch you're describing (titles persist, transcripts gone).Two things worth checking, in case the data isn't actually deleted but is in a different location than the app is reading:
find ~/.claude -name "*.jsonl" -mtime -90— lists every session transcript modified in the last 90 days. If many of your "lost" sessions show up here but not in the sidebar, the index lost track of them, not the disk. Recovery is possible by manually opening the.jsonlfiles.mv ~/projects/old-name ~/projects/new-name), the session storage stays at the old path forever and the new path looks empty. #61349 (@adamcopley) is the canonical filed case for this. The fix is to check~/.claude/projects/for orphaned directories from old working-directory names.If neither of those recovers the data, the sessions are genuinely gone from disk.
The structural pattern
Your case fits a category the community has been documenting: silent state loss without user consent. The pattern: a state artifact the user has paid for (session, memory entry, configuration, queued tool call) is silently dropped by the harness or the model, with no warning at the time of loss and no opt-in for the deletion. The user discovers the loss only by going to retrieve the artifact.
Other recent filings of the same shape:
git reset --hardagainst explicit user constraint, 3 weeks of work lost (@Awis13)What unifies them: the harness or model takes an action affecting durable state, doesn't surface the action at the time it happens, and the user only discovers it later when trying to use the state. This is a category beyond simple bugs — it's a question of what classes of action should require explicit user acknowledgment at the time, versus being acceptable to do silently.
I think you're right to be angry. Paid-for transcript data should not silently disappear, regardless of whether the underlying cause is a bug, a cleanup heuristic, or an index/disk mismatch. The "silent" part is the issue, more than the technical mechanism.
What might help in the meantime
If the
findcommand above shows the transcripts are gone from disk:~/.claude/projects/~/Library/Application Support/Claude/and~/Library/Containers/com.anthropic.claude/If the data is recoverable but the app is showing it as missing:
~/.claude/projects/somewhere and then letting the app rebuild its index sometimes reconnects orphaned.jsonlfilesI don't have a confident fix, and I'm not Anthropic. But the silent-loss question is one the cluster catalog is actively tracking; your case is a real data point regardless of how the technical recovery shakes out.
Affiliation/financial disclosure: independent (not Anthropic). I maintain cc-safe-setup and authored Claim-Verify Handbook ($19), which catalogs failure cases of this category. No purchase or citation needed to use the
findcommands above.Quick follow-up — I missed pointing you to two existing cc-safe-setup hooks that directly address this scenario, which would have been more useful than the manual
findcommand. Both are MIT-licensed, single-file, no telemetry.For future protection —
session-backup-on-start.sh. Runs on every SessionStart, copies all.jsonlfiles in the project's session directory to a timestamped backup (default~/.claude/session-backups/), keeps the last 5 backups. Originally written for #41874, the prior filing of the same silent-deletion pattern. If this had been installed before the deletion event, the 20 lost sessions would be recoverable from the timestamped backups.For the index-vs-disk mismatch you're seeing right now —
session-index-repair.sh. Runs on Stop, rebuildssessions-index.jsonfrom the actual JSONL files present in the directory. Originally written for #25032. If the sidebar entries you're seeing point to deleted JSONL files, the rebuild would clean up the index to match disk reality. If they point to JSONL files that exist but the app isn't reading, the rebuild would re-link them. Either outcome surfaces what's actually on disk.Install path for both:
The
find ~/.claude -name "*.jsonl" -mtime -90from my prior comment still applies as a one-shot diagnostic for what's currently on disk. The two hooks above are the ongoing version of the same protection.Sorry for the omission in the first reply — both hooks have been shipping in cc-safe-setup specifically for this category of failure.
One more follow-up — I built a browser-only diagnostic for the specific symptoms you described (sidebar entries with no transcripts behind them). Six questions, no signup, no telemetry:
→ Session Loss Diagnostic (90 seconds)
It routes to one of three mechanisms based on your answers (silent retention cleanup / index-disk desync / server-side outage) and generates the recovery checklist plus the operator-side hook install command. For your specific case — "sidebar entries still show but no transcript data" with "session not found on disk" — it should land on Mechanism B (index/disk desync, often recoverable if
.jsonlfiles still exist on disk).The diagnostic is built from the broader pattern writeup (7 cases April–May 2026). Hopefully something there is useful for both retrieving what's left and protecting future sessions.
This happened to me too, as someone who sometimes doesn't get back to things for . . . a while, it was very frustrating. They're potentially recoverable, here's what you actually need to do.
The first thing worth checking: open
~/.claude/projects/in Finder and see whether the.jsonltranscript files are still on disk. Each session's conversation history is stored as a.jsonlfile named by its UUID — the "Session not found on disk" error appears when the Desktop's session list still has an entry (titles survive, so it does) but the transcript file that entry is pointing to is either missing or at the wrong path.If the
.jsonlfiles are still there, when I had this the problem was in the metadata layer. On macOS, the metadata files that render the session list live at~/Library/Application Support/Claude/claude-code-sessions/— onelocal_<uuid>.jsonper session, each containing acliSessionIdfield pointing at the corresponding.jsonl. When that pointer is stale, or the metadata file itself was lost, Desktop can render the row from any cached title/date but fails to open the transcript when you click it.If that's the pattern, I built a tool you can use —
synth_session_metadata.pyfromclaude-code-session-recovery. It walks~/.claude/projects/, finds transcript files with no valid metadata pointer, and synthesises thelocal_*.jsonentries that surface those sessions back in the session list. The toolkit is Windows-tested, but the file formats are identical on macOS — the scripts need path adjustments for the macOS metadata location, but the logic transfers directly. Full write-up and macOS path notes at #56172.If the
.jsonlfiles are actually gone from~/.claude/projects/, check Time Machine —~/.claude/often falls outside people's usual backup scope but if it covers that directory and the deletion was recent, the transcripts would be there.@BasedGPT — the
synth_session_metadata.pywalkthrough is the cleanest articulation of the actual recovery mechanism I've seen in this thread, and the macOS metadata path (~/Library/Application Support/Claude/claude-code-sessions/) is the specific detail I underspecified in my earlier replies. Worth converging the recovery picture for whoever lands here next:The diagnostic that splits the cases cleanly is the one you led with: are the
.jsonlfiles still on disk under~/.claude/projects/?Case A —
.jsonlpresent, metadata stale or missing. Your tooling (synth_session_metadata.pyfrom claude-code-session-recovery, walking transcripts and synthesizing thelocal_*.jsonentries) is the right shape for this case. The bash equivalent I wrote earlier (session-index-repair.sh) does the same shape at a different layer — rebuildssessions-index.jsonagainst disk contents, but doesn't reach the macOS-specific Desktop metadata layer at~/Library/Application Support/Claude/claude-code-sessions/that your Python walker addresses. The two converge on the same operation (read disk, write metadata back) at different surface levels: the CLI session index and the Desktop session list. Operators on macOS Desktop will need the layer your tool addresses; CLI-only users can use either. Worth running both if the user is using both surfaces.Case B —
.jsonlactually gone from disk. Time Machine is the only path back here, and your callout that~/.claude/falls outside most operators' default backup scope is the part most operators don't think about until after the loss. The macOS default backup excludes some hidden directories by mtime patterns rather than path explicitly, so~/.claude/is usually included if the user hasn't customized exclusions, but operators who use Carbon Copy Cloner or other backup tools should explicitly verify the path is in scope.The independent convergence — your Windows-tested Python tooling + my bash hooks + the manual
finddiagnostic all landing on the same recovery shape — is the signal that the failure mode itself is structurally consistent across platforms, not a Windows-specific or macOS-specific artifact. Two separate operators arriving at the same metadata-vs-disk rebuild shape without coordinating is the kind of convergence that says the gap is in the harness, not in any single platform's filesystem semantics.What neither your tool nor my hooks can recover is the case where the
.jsonlfiles were truncated rather than deleted — i.e., the harness wrote a partial transcript and the metadata layer points at a file that exists but has lost messages mid-stream. The diagnostic that distinguishes "transcript intact" from "transcript truncated" is comparing message counts in the JSONL against the metadata's expectedmessageCountfield (if present) or against any sidebar indication of message count. If those disagree, the file exists but the conversation isn't recoverable from disk alone — and no rebuild of the index will surface what isn't on disk anymore.This is a separate failure mode from the one in this issue (the original report describes whole-session loss, not truncation), but it's worth flagging for the cluster: silent state loss has three points on the same axis — index loss (recoverable), partial transcript loss (partial recovery), full transcript loss (Time Machine only).
Your
synth_session_metadata.pyis reactive (recover from existing loss); thesession-backup-on-start.shhook I posted earlier is proactive (prevent future loss by snapshotting on every session start). Both are needed: backup-on-start protects against future events, synthesis recovers past events. An operator setting up defense today would install both — the backup hook for the next 90 days of sessions, the synthesis tool for the current incident.If your
claude-code-session-recoverytoolkit ever gets a macOS-tested release, threading the path differences fromsynth_session_metadata.pyinto a hook-installable form would let the toolkit slot into thecc-safe-setupexamples ecosystem. The Python implementation is the harder piece; the cc-safe-setup distribution side is just a wrapper. Happy to thread that if you want — open issue / PR / DM, whichever.Convergence on diagnosis + complementary tools (Python recovery + bash hooks + 6-question diagnostic) at this point. Useful triad for the next operator who lands here.
Hey, thanks for the breakdown — the truncation case is really useful for the toolkit.
diagnose.pycurrently surfaces "JSONL present vs JSONL missing" but doesn't check message counts against the metadata'scompletedTurnsfield. A truncated transcript looks identical to an intact one from the outside, which means the current report can give a clean bill of health to a file that's missing half its messages. I'll add an explicit check for that — the symptom would otherwise show up as "session opens but looks shorter than expected," which isn't a case I've handled. Great catch.The layer distinction is accurate —
session-index-repair.shandsynth_session_metadata.pyconverge on the same operation but at different surfaces: the CLI session index and the Desktoplocal_*.jsonfiles respectively. For macOS Desktop users, both layers are in play. Worth noting in the docs so users know which tool addresses which surface.On the proactive side — the toolkit has
backup_claude_state.pywhich snapshots both directories on demand (same intent as yoursession-backup-on-start.sh, different invocation model). There's also aworktrees/suite —backfill_recovery_stubs.py,worktree_shrink.py,worktree_inspector.ps1— that handles the worktree lifecycle specifically: preventing orphaned sessions when worktrees are removed and recovering sessions from deleted branches. That's territory your hooks don't cover, so the two toolsets end up genuinely complementary rather than just overlapping at the bash/Python layer.Happy for the cc-safe-setup integration — wrapping
synth_session_metadata.pyas an installable example once macOS paths are natively detected makes sense. I'll open an issue on the recovery side to track the macOS path work, and we can thread the wrapper from there. Full write-up at #56172.I also experienced somethnig like this with Claude Code launched via the MacOS Claude Desktop App.
My bug report describes the problem and links to a simple, safe, and effective fix-it script.
I have also lost all of my work. This will take a LOT of tokens and time to get things back to working state. This is insane. May be time to move to another solution that doesn't auto-delete all your your work and time :(
@SkeevaVR : I also keep experiencing this behavior, but the fixit scripts described here do fix the problem.
Reproduced on Windows, Claude Code desktop v1.11187.1. ~19 of 49 sessions lost ("Session not found on disk" on desktop / disconnected on mobile). Notable pattern: 11 of the 19 lost sessions had been bridged to remote/cloud sessions, vs only ~5 of the ~30 survivors — so the loss correlates with bridged sessions, not age (sessions from ~10 weeks ago survive while ones from the day before are gone). Persists after updating to the latest version and fully restarting. Local metadata flags the lost ones with transcriptUnavailable: true while keeping the title/folder, so they appear as ghost entries in the sidebar.
Hey DSP2012,
The
transcriptUnavailable: trueflag is the key data point. When I've hit this pattern, the Desktop's startup scanner has run and removedcliSessionIdfrom those metadata entries — the title stays (that's why they appear in the session list) but the pointer to the transcript file is cleared.The "Session not found on disk" message is what Desktop shows when it has a metadata entry but no valid
cliSessionIdto follow — so it doesn't necessarily mean the.jsonltranscript files have been deleted from disk.First thing worth checking: open
~/.claude/projects/(on Windows:%USERPROFILE%\.claude\projects\) and see whether.jsonlfiles exist for the affected sessions. If they're there, I built a toolkit (claude-code-session-recovery) that handles exactly this state —diagnose.pymaps each session's state across both the metadata directory and the transcript directory, andrepair_session_metadata.pybackfills thecliSessionIdlinks and removes thetranscriptUnavailableflag for sessions where the transcript is present on disk.The bridged-session correlation is an interesting pattern. My guess is that bridged sessions either write transcripts to a different location or don't create a local
.jsonlat all — the transcript lives server-side rather than in~/.claude/projects/. When the startup scanner can't find a local file to match, it flagstranscriptUnavailable. That would mean those 11 bridged sessions are a different failure class from the sessions that may still be on disk. Runningdiagnose.pywill tell you which of the 19 have local transcript files before you do anything irreversible.BasedGPT/claude-code-session-recovery
Adding ours to the pile. Same silent loss, but with a twist that made it worse for us.
We had a session that actually did something with side effects: it ran a curl that hit a third-party email API and sent a real customer a billing email. We know it happened because the email provider's dashboard shows the request (curl/8.20.0 user-agent, timestamped about an hour before we went looking). So the action definitely ran from a Claude Code session.
The session itself? Gone. I grepped every .jsonl under ~/.claude/projects, then the whole home directory. Nothing. I checked ~/.claude/history.jsonl too, which is supposed to keep your prompts even after a transcript gets deleted, and there's just a gap with nothing from that day. No .json.tmp index leftover, no backups (we hadn't set any up).
So this isn't the "hidden from the UI but still on disk" case some people are hitting. A direct disk grep finds zero. The transcript is actually gone.
What bugs me most isn't losing chat history, it's that a session touched a billing/email system and left no local record of what it did or why. We had to reconstruct it from the email provider's logs. For anything involving money or customers, that's not okay.
We've since added a SessionStart hook that backs up the jsonl files (the cc-safe-setup one mentioned upthread), but that only helps from here on. Everything already lost stays lost. Please stop deleting transcripts silently, and give us some kind of export or recovery path.
@al3rez — the side-effect angle is the part of this bug that should worry people most, and it's genuinely different from the "recover the lost transcript" cases the rest of us have been chasing here. Losing chat history is annoying; losing the only local record that a session hit a billing API is a different category of problem.
It's worth being explicit about why the transcript-backup SessionStart hook you added won't fully close this case: it snapshots whatever transcripts exist when a new session starts. A session that runs, fires the curl, and has its transcript deleted before the next
SessionStartleaves nothing to back up — which matches exactly what you saw (direct disk grep finds zero,history.jsonlhas a gap).What does survive is an independent, append-only audit written at the moment each command runs, to a path outside
~/.claude/projects(the directory the cleanup actually prunes). A tinyPreToolUsehook onBashdoes it:Register it:
I ran it against a payload identical in shape to your case (a
curl -X POST https://…/sendto an email API) and it appends one line:So next time a session touches money/customers and then vanishes, you reconstruct it from your own machine instead of the provider's dashboard.
Two honest limitations: (1) it records the command, not its output or exit status — enough to answer "what did it do," not "what did the server return"; and (2) it only covers
Bash(where curl/network side effects live), notEdit/Write. If you want the result too, aPostToolUsevariant can also appendtool_response, at the cost of a noisier log.Agreed on the core ask, though — none of this should be necessary. A session silently deleting its own only record of a side-effecting action is the part that needs fixing upstream; the hook is just a seatbelt until then.
I have also stumbled into this issue. I left a project I was working with on Claude Code for a month or two, came back, noticed that
--resumedidn't see the session, searched, looked in~/.claude/— nothing. The transcript and any evidence of it (outside Claude Code statistics) is just... gone.This wouldn't be so bad if there was a way to configure _how long to wait until pruning old sessions_, because sessions even a year or so old can become important at critical points in time.