[BUG] fetchSessions() silently drops large sessions — 64KB head/tail reader misses title data, returns null

Resolved 💬 4 comments Opened Mar 16, 2026 by dwoodruff83 Closed Apr 13, 2026

Description

fetchSessions() silently drops sessions from the "Past Conversations" list when .jsonl files exceed ~128KB and no title data lands in the first or last 64KB of the file. The session file exists on disk and is fully valid, but the listing logic returns null — making the session invisible in the UI with no error or fallback.

This is the root cause behind multiple recurring reports of session history disappearing in the VSCode extension: #12872, #29017, #9258.

Not a duplicate of #35004 or #35005 — those are panel tab restore bugs (deserializeWebviewPanel and 600s timeout). This issue is in the session listing code path (fetchSessions), which is completely separate.

Root Cause

1. oG() reads only 64KB head + 64KB tail

var R1 = 65536; // 64KB

async function oG(v) {
  let U = await E1.open(v, "r");
  let z = await U.stat();
  let j = Buffer.allocUnsafe(R1);
  let K = await U.read(j, 0, R1, 0);           // read first 64KB (head)
  let V = j.toString("utf8", 0, K.bytesRead);
  let N = Math.max(0, z.size - R1);
  let x = V;                                     // default: tail = head
  if (N > 0) {
    let O = await U.read(j, 0, R1, N);          // read last 64KB (tail)
    x = j.toString("utf8", 0, O.bytesRead);
  }
  return { mtime: z.mtime.getTime(), size: z.size, head: V, tail: x };
}

For files >128KB, everything between byte 65536 and (filesize - 65536) is never read.

2. Title resolution falls through to null

// In fetchSessions(), after oG() returns {head: N, tail: x}:
let Z = (o8(x,"customTitle") ?? o8(N,"customTitle")
      ?? o8(x,"aiTitle")     ?? o8(N,"aiTitle"))
      || o8(x,"lastPrompt")
      || o8(x,"summary")
      || eE(N);              // ← first user prompt from head

if (!Z) return null;         // ← SESSION SILENTLY DROPPED

3. eE() filters out IDE context tags

The eE(head) fallback scans the head for the first user message, but skips messages matching:

var Ca = /^(?:...|
  \s*<ide_opened_file>[\s\S]*<\/ide_opened_file>\s*$|
  \s*<ide_selection>[\s\S]*<\/ide_selection>\s*$)/;

In VSCode, most sessions begin with an <ide_opened_file> tag as the first user message — so eE() returns "", which is falsy → !Z is true → return null.

The full failure chain

For a session to be silently dropped, ALL of these must be true:

  1. File is >128KB (head ≠ tail, middle is unread)
  2. No customTitle or aiTitle record in head or tail (older session, or title pushed to middle by growth)
  3. No lastPrompt record in tail (written mid-session, now in unread middle)
  4. No summary record in tail
  5. First user message in head is an IDE-only tag (<ide_opened_file> or <ide_selection>)

This combination is common for VSCode sessions that:

  • Had extended conversations (growing past 128KB)
  • Were created before AI titling, or whose title record got pushed to the middle
  • Started with an IDE context tag (which is the default VSCode behavior)

Suggested Fix

Minimal (one-line): Never return null for a file that exists on disk:

// Current:
if (!Z) return null;

// Fixed:
if (!Z) Z = "Untitled session";

Better: Write aiTitle/lastPrompt/summary near the end of the session file periodically or at session close, so the tail reader always has something. The renameSession() method already appends aiTitle records — extending this pattern to ensure a title record is always in the tail would prevent the issue for future sessions.

Best: Use a lightweight index file for the listing instead of scanning raw .jsonl files. The CLI already maintains sessions-index.json for --resume — the extension could read it too, making the head/tail scan unnecessary.

Steps to Reproduce

  1. Create a Claude Code session in VSCode (panel or sidebar)
  2. Have a long conversation until the .jsonl file exceeds ~128KB
  3. Close VSCode, reopen it
  4. Observe: the session is missing from "Past Conversations"
  5. Verify the .jsonl file exists and is valid: ~/.claude/projects/<project>/<session-id>.jsonl

The session is more likely to disappear if:

  • It started with an <ide_opened_file> context (default in VSCode)
  • It was never AI-titled, or was titled early in the session

Workaround

Append a summary record to the end of affected .jsonl files so it falls within the last-64KB read window:

echo '{"type":"summary","summary":"<session description>"}' >> ~/.claude/projects/<project>/<session-id>.jsonl

This makes o8(tail, "summary") find the record, and the session reappears in the listing.

Environment

  • Confirmed on v2.1.76 (win32-x64), code analysis applies to all platforms
  • Affects any session whose .jsonl file exceeds ~128KB
  • More likely in VSCode than CLI due to IDE context tags in the first message

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗