[BUG] fetchSessions() silently drops large sessions — 64KB head/tail reader misses title data, returns null
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:
- File is >128KB (head ≠ tail, middle is unread)
- No
customTitleoraiTitlerecord in head or tail (older session, or title pushed to middle by growth) - No
lastPromptrecord in tail (written mid-session, now in unread middle) - No
summaryrecord in tail - 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
- Create a Claude Code session in VSCode (panel or sidebar)
- Have a long conversation until the
.jsonlfile exceeds ~128KB - Close VSCode, reopen it
- Observe: the session is missing from "Past Conversations"
- Verify the
.jsonlfile 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
.jsonlfile exceeds ~128KB - More likely in VSCode than CLI due to IDE context tags in the first message
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗