Grok Bot chat pane goes black after switching chats until interaction

Where does the bug appear (feature/product)?

Grok Bot

Describe the Bug

After switching chats in the sidebar, the main chat area (message list / frontend pane) sometimes goes mostly or fully black and stays that way until I interact with it (switch chat again, scroll, or Ctrl+A).

Looks like a render/mount failure when swapping chat views (state desync + black canvas until a repaint).

Steps to Reproduce

  1. Open Grok Bot with several chats in the sidebar.
  2. Switch from one chat to another via the left sidebar.
  3. Sometimes the chat canvas goes black. Header/composer may still show; once the header kept the previous chat title while the sidebar highlighted the new one. Occasionally a tiny clipped fragment of the bottom message bubble remains above the composer.
  4. Recovery: switch to another chat (confirmed on screencast), or scroll / Ctrl+A / any interaction in the chat area.

Screenshots / Screen Recordings

Operating System

Linux

Version Information

Grok Bot v 0.68.1

Does this stop you from using Cursor

No - Cursor works, but with this issue

Thanks for the recording, David. It clearly shows the transcript rendering after a chat switch, then turning black while the rest of the app remains visible. We’ve let the team know and are tracking this issue.

For now, Ctrl+A, scrolling, or switching chats should force the pane to redraw. Could you also confirm whether you’re using Wayland or X11?

Thanks for the reply Kevin.

Wayland — Ubuntu 24.04.4 LTS, GNOME Shell 46.0 (session type: wayland). Grok Bot 0.68.1 runs with --ozone-platform=wayland (native Wayland, not XWayland).

Exact same problem on Windows 11

Version: 0.68.1
Built: 2026-10-06T04:18:23.570Z
Release Track: stable
OS: win32

Me too! +1

Tested more on 0.68.1 (Ubuntu 24.04, GNOME 46): the black pane after switching chats reproduces the same with native Wayland, with --ozone-platform=x11 (XWayland), and with --disable-gpu-compositing. Combined with the Windows 11 report above, it looks like an app-level render/mount issue in the chat view, not a compositor/GPU one. Any interaction (scroll, Ctrl+A, switching chats) still recovers it.

Update: root cause found, plus a one-line CSS fix (verified)

I dug into this with DevTools attached to Grok Bot 0.68.1 (Electron 42.1.0 / Chrome 148, Ubuntu 24.04, GNOME 46). The short version: the app renders the transcript correctly, and Chromium’s compositor then fails to draw it. Giving the transcript plane its own compositor layer fixes it completely.

What happens

  • After switching chats, the transcript paints normally, then goes fully black about 0.6–1 s later and stays black.
  • I could reproduce it reliably by driving real mouse clicks through the sidebar over CDP and checking screenshots. About half my chats were affected, on roughly 2 of every 3 switches.

The black state is not an app-state problem

At the moment the pane is black:

  • DOM is correct: the .sand-virtual-transcript__row elements are mounted and positioned inside the viewport, scrollTop/scrollHeight/clientHeight are consistent, and elementFromPoint hits the transcript.
  • No hiding state: .sand-virtual-transcript__inner has no aria-busy or inert, and checkVisibility() is true.
  • Nothing changes when it goes black: a MutationObserver on the whole document records zero DOM mutations in the 600–1600 ms window. Computed styles of the transcript and its ancestors are identical before and after.
  • No overlay: nothing covers the pane (no iframe, webview, video, canvas, or pointer-events: none layer).
  • No repaint: the CDP LayerTree is unchanged, including paint counts, so the main thread never repainted. The pixels changed only on the compositor/raster side.

That also explains why --ozone-platform=x11, Wayland, and --disable-gpu-compositing all behave the same, and why it shows up on Windows too.

What does and doesn’t bring it back (applied while the pane is black)

Nudge Recovers?
Invalidate the plane’s paint (outline: 1px solid transparent on .sand-virtual-transcript__inner) no
scrollTop -= 1 on the scroller no
Toggle data-sand-style-release on <html> (sync, or held across frames) no
will-change: transform on .sand-virtual-transcript__inner yes, instantly
Translucent background on .sand-virtual-transcript (lets Chromium composite the scroller) yes, instantly

Only changes that give the transcript its own compositor layer recover it.

Prevention test

I applied each CSS rule up front, then ran the same switch loop: 12 switches across the affected chats, 2 s after each, screenshot luminance check.

CSS Black switches
none (baseline) 8 / 12
.sand-virtual-transcript__inner { will-change: transform } 0 / 12
.sand-virtual-transcript { background-color: rgba(1,1,1,.01) } 0 / 12

Things I ruled out

  • First-layout reveal gate (aria-busy → clip-path: inset(100%)): it does flash on for about 5 ms during a switch, but overriding it to clip-path: none made no difference.
  • Virtual-list window or scroll-offset race: rows are in the viewport and the offsets are right in the black state.
  • Image attachments: some affected chats have no images.
  • The data-sand-style-release style-flush toggle: it only fires when previously mounted rows are removed, so it never runs on the fresh mount after a chat switch. Running it manually doesn’t recover the pane either.

Suggested fix

Add this to the transcript plane:

.sand-virtual-transcript__inner { will-change: transform; }

Any equivalent that gives the plane its own compositor layer should also work. It may also be worth reporting to Chromium, since the trigger seems to be a tall, non-composited overflow scroller with absolutely positioned translateY rows.

Local workaround (Linux, until a fix ships)

I patched my local resources/app.asar by replacing the empty rule html[data-sand-style-release] .sand-style-release-never{color:inherit} with the rule above. It’s a same-length, in-place byte edit, so no repack is needed, and Electron’s asar integrity check doesn’t block it on Linux. After the patch the black pane is completely gone for me. An app update will overwrite it, of course.

cc: @kevinn