VSCode webview hardcoded 500-message render cap silently truncates session scrollback
Affected: anthropic.claude-code 2.1.126 (Antigravity / VSCode extension webview).
Symptom
Sessions with more than ~600 message events in the chain cap out at the last 500 messages
in the chat panel, regardless of how many the extension's getSession returned. There is no
"load more" affordance, no error, and no indication that messages were dropped.
This affects:
- Long-running sessions (many turns)
- Sessions with many tool_use / tool_result events
- Especially: sessions where chain walking before the compact boundary has been restored (via the
logicalParentUuid fallback referenced in #48937 secondary / #46603); once the chain
walker returns thousands of messages, only the last 500 reach the user's eyes.
Root cause
In the bundled webview/index.js, a function (minified OD($) in 2.1.126) caps the
session-message array before assigning it to React state:
function OD($) {
if ($.length > 600) { // g20 = 600
let Z = $.length - 500; // u20 = 500
return $.slice(Z); // keep last 500 only
}
return $;
}
Called from loadFromServer immediately before this.messages.value = OD(wD(J)).
The cap is hardcoded: no user-facing setting, no env var, no scroll-to-load-more. Whatever
the extension's getSession() returned via the get_session_request IPC, the webview
silently drops everything except the last 500 entries.
Reproduction
- Open any session in VSCode/Antigravity whose chain walker yields > 600 messages
(sufficiently long active session, or one where compaction-boundary chain bridges have
been restored).
- Verify via
getSession()(e.g., from the webview console: readsession.connection.v
then call conn.getSession(sessionId)) that the IPC response carries N messages.
- Verify that
session.messages.value.length === Math.min(N, 500); the in-state count
never exceeds 500.
- Scroll to the top of the chat panel: it ends at the (N-500)+1th message.
Empirical observation on a session with N = 1857 the webview state contained exactly
500 messages. After replacing OD with a no-op identity (function OD($){return $}),
state contained all 1857.
Why this is a bug
- The cap predates and is independent of any chain-walker / compaction logic. It treats any
message overflow the same way: silently drop the oldest.
- There is no UI feedback. A user who knows their conversation has thousands of turns has
no signal that the panel is showing only the most recent 500.
- For users who rely on session scrollback to recall earlier context, decisions, or links,
this is a silent data-loss UX. They see the rendered start of conversation as if it's
the actual start.
- The cap interacts adversarially with #48937 / #46603 fixes: the entire point of restoring
visibility of messages before the compact boundary is to let users scroll back further. The 500 cap negates
that effort once the chain becomes long enough.
Suggested fix
A few options, in order of cleanness:
- Lazy/virtualized rendering: keep the full message list in state, render in
windows. Modern React lists handle 10K+ items with virtualization. (The Messages
component in the leaked source's REPL path uses
MAX_MESSAGES_WITHOUT_VIRTUALIZATION = 200 as a virtualization-toggle threshold;
the webview should adopt similar behavior rather than silent truncation.)
- Chunked load on scroll: initial load gives e.g. 1000 most recent; scrolling near
the top loads the next chunk from getSession({offset, limit}) (the loader already
accepts offset/limit; Cz4(G, K) applies them).
- At minimum: surface the truncation in the UI ("N earlier messages hidden, click
to load all"). This keeps the cap as a perf safety but tells the user it's happening.
_Call chain from get_session_response to the React state setter walked by an instance of Claude Opus 4.7. The leak made the 500-message cap visible as a named constant rather than an observed behavioral limit, and exposed the existing MAX_MESSAGES_WITHOUT_VIRTUALIZATION = 200 threshold in the REPL path, which is the design precedent for the fix proposal above. Without readable source, this would have been "the webview stops showing messages after a while" with no proposal grounded in what's already in the codebase. Working with the user._
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗