Streaming rendering broken for months: content flickers on settle, user cannot scroll up during streaming
#6,414 opened on Jul 22, 2026
Repository metrics
- Stars
- (16,904 stars)
- PR merge metrics
- (Avg merge 14h 31m) (314 merged PRs in 30d)
Description
Streaming rendering is broken: content flickers on settle, user can't scroll up during streaming
Versions affected: v0.52.0 through latest v0.52.76 (confirmed on v0.52.0, v0.52.41, v0.52.76)
Environment: Linux, Chrome/Firefox latest, Desktop
I've spent significant time debugging these issues. They make the WebUI nearly unusable for daily use. I'm genuinely disappointed — this has been going on for dozens of releases without a fix.
Issue 1: Content flickers on settle
When a streaming response finishes ("done" event), the worklog rows get re-rendered. The deferred DOM approach (introduced in #5839) builds lightweight shell elements during streaming, then replaces them with real DOM post-processed nodes on settle. This replacement triggers a layout reflow that visibly flickers the entire activity pane.
The root cause is in _materializeDeferredWorklogRows() (ui.js) — the deferred rows are built via requestAnimationFrame, causing the swap to span two frames and producing a visible flash.
Issue 2: User cannot scroll up during streaming
When the user scrolls up to read history while a response is streaming, the scroll listener's _programmaticScroll guard in messages.js suppresses the unpin:
if(_programmaticScroll) return;
During streaming, renderMessages({preserveScroll:true}) fires every ~100ms. Each call sets _programmaticScroll=true for ~16ms (deferred clear via rAF + setTimeout(0)). This means _programmaticScroll is active ~16% of the time constantly — the user's upward scroll events are swallowed, _messageUserUnpinned never gets set, and the next preserveScroll render yanks the viewport back to the bottom.
Wheel/touch intent bypasses exist but don't help when the guard fires before the intent is registered.
Issue 3: Scroll position jumps on large scrolls after settle
Even when the user successfully scrolls up, the worklog collapse on settle ("Done in Xs" summary) reduces content height by hundreds of pixels. The absolute-pixel scroll restoration (scrollTop = maxTop - bottom) can't compensate for the height change, causing the viewport to jump upward by the collapse delta.
The keepSettledWorklogOpen mechanism (#5260) tries to prevent this but it's a single-shot token that doesn't cover all settle paths.
Attempted workarounds
I tried:
chat_activity_display_mode: compact_worklog/transparent_stream/hide_all_activity— none fix it- Adding
contain: style layoutto activity groups — breaks overflow-anchor - Disabling deferred worklog DOM entirely — helps flicker but not scroll
- Keeping worklog expanded after settle — helps scroll but makes activity area always visible
None is a complete solution. The rendering pipeline needs a redesign to avoid the full-DOM-replacement settle dance. A virtual-scroll or incremental-update approach (like every other chat UI uses) would be far more stable.
What's needed
The core problems are:
- Don't replace the streaming DOM wholesale on settle. Incremental updates only.
- Don't let
_programmaticScrollsuppress real user input. User intent detection should take priority over render bookkeeping. - Either keep worklog height stable across settle, or use semantic scroll anchoring instead of absolute pixel positions.
Six dozen releases and none of these have been addressed. This needs attention.