sessions-index.json not updated, causing `claude --resume` to show stale/missing sessions

Status Closed — duplicate
Reported on v2.1.39
Maintainer reply None cached
Activity 15 comments · opened Feb 11, 2026 · closed Aug 19, 2026

Bug Description

claude --resume only shows a random smattering of old sessions (from ~2 weeks ago), despite having run many sessions recently. The session data itself is being saved correctly — the .jsonl files are all present on disk — but they don't appear in the resume picker.

Root Cause (identified with Claude's help)

The sessions-index.json files in ~/.claude/projects/ are either:

  1. Missing entirely for many active project directories
  2. Stale — not being updated when new sessions are created

For example, on my system (v2.1.39, macOS):

  • 11 out of 18 project directories have no sessions-index.json at all, including directories with very recent session activity
  • The index files that do exist haven't been updated since late January, despite session .jsonl files being written as recently as today
HAS INDEX: -Users-...-dev-ozzydb (Feb  4)   ← stale, sessions exist from Feb 10
NO INDEX:  -Users-...-dev-rileyviewer        ← no index, 20MB+ session from Feb 10
NO INDEX:  -Users-...-dev                    ← no index, sessions from Feb 10
NO INDEX:  -Users-...-hard-saptest1          ← no index, sessions from Feb 10

The session .jsonl files are all intact — data is not being lost. But since --resume appears to read from sessions-index.json, these sessions are invisible to the resume picker (both CLI and VS Code extension).

Steps to Reproduce

  1. Run several Claude Code sessions across different project directories
  2. Close them (I typically just close the terminal)
  3. Run claude --resume — only old sessions appear
  4. Check ~/.claude/projects/*/sessions-index.json — many are missing or stale
  5. Check for .jsonl files — they exist and are recent

Expected Behavior

claude --resume should list all recent sessions, and sessions-index.json should be updated whenever a session is created or modified.

Environment

  • Claude Code version: 2.1.39
  • OS: macOS (Darwin 25.1.0)
  • Sessions are closed by closing the terminal (no explicit exit command)

Notes

I found this bug myself; Claude helped identify the specific root cause (the stale/missing index files) by examining the session storage on disk.

View original on GitHub ↗

14 Comments

RileyLeff · 6 months ago

Additional finding: The local usage tracking at ~/.claude/usage-data/ appears to have the same problem. Both the report.html and per-session facet JSONs stopped being updated on Feb 4, despite active sessions running through Feb 10-11. This suggests it may be a broader issue with local metadata/index writes, not just sessions-index.json.

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/22462
  2. https://github.com/anthropics/claude-code/issues/23614
  3. https://github.com/anthropics/claude-code/issues/24729

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

genesiscz · 6 months ago

Confirmed: Same issue here (macOS)

Can confirm this bug on macOS with similar findings:

Environment

  • OS: macOS (Darwin 25.2.0)
  • Claude Code: 2.1.39+
  • 8 project directories checked

Findings

Session indexing completely stopped on: February 4, 2026 at 00:33 UTC

  • All 8 project directories have sessions-index.json files
  • Last indexed session across all projects: Feb 4, 2026, 00:33:54 UTC
  • Total session files on disk: 3,080+ .jsonl files
  • Latest session file: Feb 12, 2026 (today) - NOT indexed
  • Sessions created after Feb 4: 0% indexed

Example from one project:

Project: [redacted]
  Total .jsonl files: 809
  Indexed in sessions-index.json: 217
  Latest indexed: Feb 4, 00:33 UTC
  Latest .jsonl file: Feb 12, 17:38 UTC (today)
  Missing from index: 592 sessions (73%)

Empty Summaries Also Present

Some indexed sessions (created before Feb 4) have empty summaries:

  • Project A: 72/280 sessions (26%) with empty summaries
  • Project B: 92/112 sessions (82%!) with empty summaries

This suggests two separate issues:

  1. Summary generation degraded starting late January (some summaries empty)
  2. Indexing completely stopped on Feb 4, 00:33 UTC (no new entries)

Potential Connection to #16157

The timeline aligns suspiciously with the usage quota bug (#16157):

  • Jan 19-26: Anthropic announces "rolled out changes to reduce token usage" (comment)
  • Late January: Session summaries start becoming empty (costs tokens to generate)
  • Feb 4, 00:33 UTC: Session indexing completely stops

Session summary generation requires API calls (potentially 100K+ input tokens per session × all users). Disabling this would significantly reduce token consumption, which may have been an emergency response to the usage crisis.

Whether this was intentional cost-cutting or an unintended side effect of the late-January changes is unclear, but the timing is too coincidental to ignore.

tirufege · 6 months ago

I can confirm this issue on Linux (Ubuntu, Claude Code 2.1.41).

Findings:

  • sessions-index.json has 28 entries, with the newest modified date being January 23, 2026
  • Meanwhile, there are 127 .jsonl session files on disk, including many from February 10-13
  • That means 99 sessions created after late January are completely missing from the index
  • Sessions show up in the /resume picker (presumably from the .jsonl files), but clicking on them gives "Session was not found" because the index lookup fails

Workaround:
I wrote a Python script that parses all .jsonl files on disk and rebuilds the missing entries in sessions-index.json — extracting firstPrompt, customTitle, messageCount, timestamps, etc. from the raw session data. After running it, /resume works again for all sessions.

Happy to share the script if anyone needs it.

Environment:

  • Claude Code: 2.1.41
  • OS: Linux 5.15.0-164-generic (Ubuntu)
  • cleanupPeriodDays: 3650
tirufege · 6 months ago

Here's the repair script I mentioned: https://gist.github.com/tirufege/0720c288092c1a3a4750f7c198aa524b

It scans all .jsonl session files on disk, extracts metadata (first prompt, custom title, message count, timestamps), and adds missing entries to sessions-index.json. Creates a .bak backup before writing.

# Repair all projects
python3 repair-sessions-index.py

# Repair a specific project directory
python3 repair-sessions-index.py ~/.claude/projects/-home-user-myproject
scapeshift-ojones · 6 months ago

This issue is tracked in the consolidated report at #26123, which identifies 3 distinct root causes (index writes stopped Feb 4, picker hardcoded to 10-session batch, Windows worktree case-sensitivity) with source-level analysis and a one-line fix. Please add your thumbs-up there to help it reach the oncall triage threshold.

scapeshift-ojones · 6 months ago

Your 👍 on the consolidated issue matters. Based on how this repo's automated triage works, issues need 50+ combined reactions and comments to trigger the oncall label — the only way a human at Anthropic actually reviews it. Right now the engagement is split across 12+ duplicate issues and none will ever hit that threshold alone.

The consolidated issue with full root cause analysis (3 bugs identified, one-line fix included) is here: #26123

Please go add your 👍 there. That's the single most useful thing you can do to get this fixed.

scapeshift-ojones · 6 months ago

We're at 22 👍 on the consolidated issue — more than halfway to the 50 needed to get a human at Anthropic to look at this. Every thumbs-up on a duplicate issue is a thumbs-up that doesn't count. The automated triage bot only checks individual issues, not the cluster.

Please take 5 seconds to 👍 here: #26123

The root causes are fully identified, a one-line fix exists, and community repair scripts are available. The only thing missing is enough engagement on a single issue to cross the oncall threshold. We can get this fixed if we stop splitting our votes across 12 separate reports.

vbhavsar · 6 months ago

Status Update: This is fixed in v2.1.50

After investigating the compiled binary and CHANGELOG, here's what happened and the current state:

The sessions-index.json was intentionally removed

In v2.1.30, the session index file was replaced with direct filesystem scanning — the --resume picker now discovers sessions by stat-ing .jsonl files on disk instead of maintaining a centralized index. This reduced memory usage by 68%.

The string sessions-index does not exist anywhere in the v2.1.50 binary. The stale/missing index files on disk are harmless leftovers — the CLI no longer reads or writes them.

Multiple bugs in the new stat-based system caused the reported behavior

| Bug | Fixed In | Issue |
|-----|----------|-------|
| Resume picker only loaded 10 sessions initially (most sessions invisible) | v2.1.47 | #26123 |
| Sessions with >16KB first messages silently dropped from list | v2.1.47 | #25721, #25920, #26140 |
| Symlink path resolution mismatch made sessions invisible | v2.1.50 | — |
| Session data loss on SSH/terminal disconnect (data not flushed before shutdown) | v2.1.50 | — |

How --resume works now (v2.1.50)

  1. Scans all .jsonl files via readdirSync + statSync
  2. Sorts by modification time (most recent first)
  3. Deduplicates by session ID
  4. Progressively reads first/last 64KB of each file for metadata (title, branch, first prompt, etc.)
  5. Loads up to 50 sessions initially (up from 10)

Action items

  • Upgrade to v2.1.50 — all known root causes are fixed
  • The old sessions-index.json files can be safely deleted — they're no longer used
  • No repair scripts needed on current versions

🤖 Generated with Claude Code

ThatDragonOverThere · 6 months ago

Custom Names Broken Too — Feb 23, 2026

Adding another dimension to this: even sessions that DO appear in the picker don't show their custom names.

I have 6 concurrent sessions, all renamed via /rename. Terminal tab titles show the correct names. The Ctrl+E picker shows auto-generated summaries for every single one.

The index staleness (#26123 Bug 1) was supposedly addressed by direct .jsonl scanning in v2.1.47, but custom names set via /rename are stored in the JSONL and the picker apparently never reads them back.

The combination is brutal:

  1. Index is stale → many sessions don't appear at all
  2. Sessions that DO appear → show wrong names (auto-summary instead of custom name)
  3. Bun crashes every 1-3 hours on Windows (#21576, 17 repros) → forced to resume constantly
  4. Every resume = guessing game across 6 unnamed sessions

This is a daily-driver workflow blocker. Day 5 reporting.

Version: Claude Code latest, Bun v1.3.10, Windows 11
Related: #25090, #26123, #24729

sstklen · 6 months ago

Hey! I ran into a similar pattern in our bug knowledge base and thought this might help.

What's happening: Regression in Claude Code ~v2.1.x (around Feb 4 2026) broke the session-index writer. Session .jsonl files are still written but sessions-index.json is no longer updated on session create/end. The index writer likely fails silently (swallowed error or dead code path after refactor).

What worked for us:

Rebuild all sessions-index.json files from existing .jsonl session data on disk. Run this one-liner to regenerate every project's index. For the permanent fix, Anthropic needs to patch the index writer in the CLI source.

#!/usr/bin/env bash
# Rebuild all sessions-index.json from .jsonl session files
# Run: bash rebuild-session-index.sh

shopt -s nullglob
CLAUDE_DIR="${HOME}/.claude/projects"

for project_dir in "${CLAUDE_DIR}"/*/; do
  sessions_dir="${project_dir}sessions"
  index_file="${project_dir}sessions-index.json"
  [ -d "$sessions_dir" ] || continue

  entries="[]"
  for jsonl in "${sessions_dir}"/*.jsonl; do
    session_id=$(basename "$jsonl" .jsonl)
    # First line has the init message with timestamp
    first_line=$(head -1 "$jsonl" 2>/dev/null)
    last_line=$(tail -1 "$jsonl" 2>/dev/null)
    
    start_ts=$(echo "$first_line" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('timestamp',''))" 2>/dev/null)
    end_ts=$(echo "$last_line" | python3 -c "import sys,json; print(json.loads(sys.stdin.read()).get('timestamp',''))" 2>/dev/null)
    # Extract summary/title from first user message
    summary=$(echo "$first_line" | python3 -c "
import sys,json
m=json.loads(sys.stdin.read())
text=m.get('message',{}).get('content','')
if isinstance(text,list): text=next((b.get('text','') for b in text if b.get('type')=='text'),'') 
print(text[:80])" 2>/dev/null)
    
    [ -z "$start_ts" ] && continue
    entries=$(echo "$entries" | python3 -c "
import sys,json
arr=json.loads(sys.stdin.read())
arr.append({'sessionId':'$session_id','startedAt':'$start_ts','lastActiveAt':'${end_ts:-$start_ts}','summary':'''$summary'''})
print(json.dumps(arr))")
  done

  # Sort by lastActiveAt descending and write
  echo "$entries" | python3 -c "
import sys,json
arr=json.loads(sys.stdin.read())
arr.sort(key=lambda x:x.get('lastActiveAt',''),reverse=True)
print(json.dumps(arr,indent=2))" > "$index_file"
  
  count=$(echo "$entries" | python3 -c "import sys,json;print(len(json.loads(sys.stdin.read())))")
  echo "Rebuilt $index_file ($count sessions)"
done

Hope this helps! Let me know if it doesn't match your case — happy to dig deeper. 🦞

_Disclosure: This analysis is from Confucius Debug, an AI-powered community KB for agent bugs. Please verify before applying._

---
<sub>🦞 Confucius Debug — community knowledge base for AI agent bugs. Free to search via MCP.</sub>

Flowburghardt · 5 months ago

Confirming on macOS — Claude Code v2.1.63

Same issue here. sessions-index.json silently stopped updating on February 3, 2026 and has not recovered since.

Environment

  • OS: macOS Sonoma 14.7 (Darwin 23.6.0)
  • Claude Code: v2.1.63
  • Interface: VS Code extension + CLI

Diagnostics

JSONL files on disk:     471
Entries in index:        255
Missing from index:      216 sessions (~1 month of work)
Last indexed session:    2026-02-03T23:40:38Z
Latest JSONL on disk:    2026-03-03 (today)

The sessions-index.json structure looks correct (version 1, proper entries with sessionId/fullPath/fileMtime/firstPrompt etc.), but new sessions simply aren't being appended. All JSONL files are valid JSON, proper permissions (-rw-------), and contain intact user/assistant message chains.

Impact

  • "Past Conversations" in VS Code shows only sessions from before Feb 3
  • Selecting a listed session loads it as blank/empty (possibly because the index metadata is stale while the file has changed)
  • claude --resume in terminal works correctly — it reads directly from disk, bypassing the index

Workaround

claude --resume (CLI) correctly lists all sessions since it appears to scan .jsonl files directly rather than relying on the index. The VS Code "Past Conversations" picker remains broken.

michael-wojcik · 5 months ago

FYI the sessions-index.json approach here is moot on current versions (removed in v2.1.30), but the problem persists. I did a fresh investigation on v2.1.81 in #38340. Even with the stat-based replacement, the picker still doesn't scan for .jsonl files. Confirmed via strace and by manually creating a valid session file that the picker never discovered.

cybersader · 4 months ago

Stale sessions-index.json — 14 projects drifting up to 93 days on one machine, hypothesized mechanism

Hit this on WSL2, v2.1.118, single-OS (not the cross-platform fragmentation from #17682 / #9668 / #9306). Posting because the cumulative-drift evidence and the mechanism hypothesis tying graceful-shutdown dependency to overwrite-of-cached-state don't appear to be in the thread yet.

Environment

  • WSL2 on Windows (Linux 6.6.87.2-microsoft-standard-WSL2)
  • Claude Code v2.1.118 (Bun-bundled binary at ~/.local/share/claude/versions/2.1.118)
  • Single ~/.claude/projects/ bucket per project — not cross-OS-dual-encoded for the projects showing drift

Symptom

/resume picker reports one of my active sessions as a 9-message stub last modified 2026-01-09, with summary "OpenCode permissions setup and Terminal Workspaces bug fix."

Actual state of the .jsonl:

  • Size: 59 MB
  • Last .jsonl append: 2026-04-23 02:22 UTC (the current session I was in when I opened the picker)
  • Continuous append activity from 2025-12-10 through 2026-04-23 — about four months of real resume-ed work

The .jsonl content is clean and picker-loadable via claude -r <uuid> (bypass the picker). The index is the only broken artifact.

Cumulative drift — 14 projects on this machine

Scan of ~/.claude/projects/*/ on 2026-04-23, flagging projects where sessions-index.json mtime lags the newest non-subagent .jsonl mtime by more than 7 days:

| Project (tail of encoded name) | Lag |
|---|---|
| -mnt-d-MEDIA | 93d |
| home-assistant-projects | 90d |
| …tasknotes…obsidian-plugins-tasknotes (duplicate-encoded) | 84d |
| …tasknotes-enhancements | 80d |
| cynario | 79d |
| retake-studio | 66d |
| 4-VAULTS | 65d |
| …terminal-workspaces | 57d |
| b-g-33---Home-Lab--Home-Server | 57d |
| b-g-15---Family-Planning--Parenthood | 46d |
| 3d-printing | 44d |
| b-g-vault-b-g, …tasknotes…plugins-tasknotes (dot-prefix variant) | 12d each |
| DFD-Excalidraw-System | 11d |

This rules out one-time WSL crash. It's consistent with every ungraceful close dropping an index update, accumulating across months of normal WSL lifecycle (window-close without typing /exit, wsl --shutdown, machine suspend, OOM-kill).

Mechanism hypothesis — graceful-shutdown is necessary but not sufficient

  1. Ungraceful-shutdown path clearly breaks. SIGKILL / forced WSL shutdown / suspend skip application-side signal handlers and atexit — index update is lost, .jsonl survives because it's append-on-write.
  1. Clean-exit path also loses entries per #41946. So the bug isn't purely "SIGKILL skips flush."
  1. A Zenn writeup (tjst_t) notes the index "rolled back two weeks" after a recovery attempt — suggests the rewrite path re-reads cached in-memory state and overwrites the on-disk index, rather than merging with the current filesystem state. Combined with racy writes on any abnormal timing, that would produce the cumulative drift pattern I see on this machine.
  1. @agatho's #24729 comment points to a case-sensitivity bug in the multi-worktree code path (function xa in the minified cli.js). Other commenters confirm the bug triggers without worktrees too, which is what I observed.

So the fuller mechanism is likely: the write path is both racy against forced-kill AND regresses state on some graceful closures, because it re-reads a cached snapshot rather than merging with reality.

sessions-index.json format (as observed — this is not documented publicly)

{
  "version": 1,
  "entries": [
    {
      "sessionId": "uuid-36-chars",
      "fullPath": "/abs/path/to/<sessionId>.jsonl",
      "fileMtime": 1769531155388,
      "firstPrompt": "first 200 chars of first user message",
      "customTitle": "…",          // optional, from type:custom-title records
      "summary": "…",              // optional, LLM-generated on graceful exit?
      "messageCount": 9,
      "created": "2026-01-09T15:38:59.766Z",
      "modified": "2026-01-09T15:48:27.815Z",
      "gitBranch": "",
      "projectPath": "/abs/project/path",
      "isSidechain": false
    }
  ],
  "originalPath": "/abs/project/path"
}

Fully undocumented in docs.anthropic.com / docs.claude.com. It would help third parties considerably if the schema were published, even as a footnote.

Workaround landscape (no Anthropic fix required to use these, but none should need to exist)

Third-party tools converging on two shapes:

  • Rebuild the index. tirufege's Python gist is the original; I shipped a Rust port as pconv rebuild-index with atomic writes, dated backup, and a doctor counterpart for read-only detection. Round-trip tested against the schema above — pconv rebuild-index --all followed by pconv doctor reports zero stale projects.
  • Replace the picker. KirillPuljavin/cres, riii111/claude-resume — both read .jsonls directly and ignore the index.

Asks for Anthropic

Prioritized:

  1. Rebuild-on-startup-if-stale. On every launch, if sessions-index.json is missing OR lags the newest .jsonl in the same dir by >24h, regenerate it from the .jsonls before showing the picker. Cheap (<100 ms for the largest project I have; likely faster than what the picker already does).
  2. Switch write path from overwrite-with-cached-snapshot to merge-with-filesystem. Addresses the "rolled back two weeks" regressions even on graceful exit.
  3. Document the sessions-index.json format publicly. Footnote-length; enables the third-party ecosystem to operate on stable ground rather than reverse-engineering per-version.
  4. Consider emitting a warning from /resume when picker results disagree with .jsonl mtimes by more than N days. Even without an auto-fix, a hint like "the picker may be stale; consider running claude --rebuild-index or pconv rebuild-index" would close the feedback loop for users.

Reproducibility hints for whoever picks this up

strace -fe trace=openat,rename,write,fsync -p $(pgrep -f claude) through a session, then diff index state across /exit vs wsl --shutdown vs SIGKILL, would pin the write cadence. I haven't done this myself because claude -r <uuid> and pconv rebuild-index unblock me today; but the drift pattern I report above is strongly suggestive of the hypothesis above.

---

References:

Showing cached comments. Read the full discussion on GitHub ↗