Problem Description
The chat view scrollbar jumps to the middle of the conversation during long streaming sessions, making it impossible to follow the latest messages. This occurs when conversations exceed 500 messages and is caused by array index shifting in the virtual scrolling implementation.
Root Cause Analysis
The Index Shifting Bug
The issue stems from the message filtering logic in webview-ui/src/components/chat/ChatView.tsx at lines 899-902:
const visibleMessages = useMemo ( ( ) => {
const currentMessageCount = modifiedMessages . length
const startIndex = Math . max ( 0 , currentMessageCount - 500 )
const recentMessages = modifiedMessages . slice ( startIndex )
// ...
When a conversation exceeds 500 messages, each new message causes:
The startIndex to increment by 1
The oldest message to be dropped from the array
All remaining messages to shift down by one index position
Virtuoso (the virtual scrolling library) to lose track of the current position
The Sequence of Events
Initial State : User is viewing message at index 499 (bottom of 500-message window)
New Message Arrives : Total messages become 501
Array Mutation :
startIndex changes from 0 to 1
Message at index 0 is dropped
Messages 1-500 become indices 0-499
New message is added at index 499
Position Lost : Virtuoso was tracking index 499, but that index now contains different content
View Jumps : The viewport jumps to approximately the middle of the conversation (around index 250)
Why Current Fixes Don't Work
Number.MAX_SAFE_INTEGER scrolling (lines 1337, 1351): This correctly scrolls to bottom, but array mutations happen between scroll commands
Auto-scroll timing (line 1395): Auto-scroll fires every 50ms, but array shifts happen immediately when messages arrive
PR fix: improve auto-scroll behavior during API activities and streaming #6989 : Helps by keeping auto-scroll active during streaming, but doesn't address the underlying array mutation issue
Reproduction Steps
Start a new conversation with Roo Code
Continue the conversation until it exceeds 500 messages
Observe that during streaming, the view jumps to the middle of the conversation
Scrolling down manually doesn't help as it keeps jumping back up
Technical Details
Affected Components
webview-ui/src/components/chat/ChatView.tsx
React Virtuoso virtual scrolling library
Message array management (lines 899-963)
Related Code Sections
Message filtering: Lines 899-902
Virtuoso configuration: Lines 1869-1885
Auto-scroll logic: Lines 1390-1400
Scroll methods: Lines 1335-1356
Proposed Solutions
Option 1: Remove Message Limit (Recommended)
Remove the 500-message slice entirely and let Virtuoso handle virtualization of all messages:
const visibleMessages = useMemo ( ( ) => {
// Remove the slicing logic
const newVisibleMessages = modifiedMessages . filter ( ( message : ClineMessage ) => {
// Keep existing filter logic
} )
// ...
Pros :
Completely eliminates index shifting
Virtuoso is designed to handle large lists efficiently
Simplest fix
Cons :
Slightly higher memory usage (but still bounded by Virtuoso's virtualization)
Option 2: Track by Stable Keys
Configure Virtuoso to track items by message timestamp (ts) instead of array index:
< Virtuoso
ref = { virtuosoRef}
key = { task . ts}
className = "scrollable grow overflow-y-scroll mb-1"
increaseViewportBy = { { top : 3_000 , bottom : 1000 } }
data = { groupedMessages}
itemContent = { itemContent}
computeItemKey = { ( index , item ) => Array . isArray ( item ) ? item [ 0 ] . ts : item . ts }
// ...
/ >
Pros :
Maintains current memory optimization
Virtuoso can track position even with array mutations
Cons :
Requires testing to ensure Virtuoso handles key-based tracking correctly
Option 3: Force Re-scroll on Array Mutation
Detect when startIndex changes and immediately scroll to bottom:
const prevStartIndexRef = useRef ( 0 )
useEffect ( ( ) => {
const currentMessageCount = modifiedMessages . length
const startIndex = Math . max ( 0 , currentMessageCount - 500 )
if ( startIndex !== prevStartIndexRef . current && ! disableAutoScrollRef . current ) {
scrollToBottomAuto ( )
prevStartIndexRef . current = startIndex
}
} , [ modifiedMessages . length ] )
Pros :
Minimal change to existing code
Preserves memory optimization
Cons :
May cause visible jumps when re-scrolling
Doesn't fix the root cause, just mitigates symptoms
Impact
Testing Requirements
Create a conversation with 600+ messages
Verify scrolling stays at bottom during streaming
Verify manual scroll-up is respected
Verify memory usage remains reasonable
Test with various message types (code blocks, images, etc.)
Related Issues and PRs
Additional Context
This investigation revealed that while PR #6989 helps with auto-scroll behavior, it doesn't address the root cause of array index shifting. A proper fix requires preventing the array indices from changing when new messages arrive in long conversations.
The issue is particularly problematic because:
It makes long conversations effectively unusable
Users cannot follow along with streaming responses
Manual intervention (scrolling) doesn't help as the view keeps jumping
@roomote-agent This issue needs immediate attention as it significantly impacts user experience in long conversations.
Problem Description
The chat view scrollbar jumps to the middle of the conversation during long streaming sessions, making it impossible to follow the latest messages. This occurs when conversations exceed 500 messages and is caused by array index shifting in the virtual scrolling implementation.
Root Cause Analysis
The Index Shifting Bug
The issue stems from the message filtering logic in
webview-ui/src/components/chat/ChatView.tsxat lines 899-902:When a conversation exceeds 500 messages, each new message causes:
startIndexto increment by 1The Sequence of Events
startIndexchanges from 0 to 1Why Current Fixes Don't Work
Number.MAX_SAFE_INTEGERscrolling (lines 1337, 1351): This correctly scrolls to bottom, but array mutations happen between scroll commandsReproduction Steps
Technical Details
Affected Components
webview-ui/src/components/chat/ChatView.tsxRelated Code Sections
Proposed Solutions
Option 1: Remove Message Limit (Recommended)
Remove the 500-message slice entirely and let Virtuoso handle virtualization of all messages:
Pros:
Cons:
Option 2: Track by Stable Keys
Configure Virtuoso to track items by message timestamp (
ts) instead of array index:Pros:
Cons:
Option 3: Force Re-scroll on Array Mutation
Detect when
startIndexchanges and immediately scroll to bottom:Pros:
Cons:
Impact
Testing Requirements
Related Issues and PRs
Additional Context
This investigation revealed that while PR #6989 helps with auto-scroll behavior, it doesn't address the root cause of array index shifting. A proper fix requires preventing the array indices from changing when new messages arrive in long conversations.
The issue is particularly problematic because:
@roomote-agent This issue needs immediate attention as it significantly impacts user experience in long conversations.