The Mystery White Screen Was Chrome Translate Fighting React. We Killed It. (v2.1.15 Is Out)

Share
The Mystery White Screen Was Chrome Translate Fighting React. We Killed It. (v2.1.15 Is Out)

A few clients had been reporting an intermittent blank page in their dashboards over the last week. The kind of bug you hate: random, no reliable reproduction, dev console shows a single ugly stack trace from minified React internals, nothing in our logs. Refresh and the page comes back. Until the next time.

We finally tracked it down. v2.1.15 ships the fix, plus two smaller cleanups in the conversation history panel that we caught on the way.

The bug that wasn't ours

The error trace looked like this:

NotFoundError: Failed to execute 'removeChild' on 'Node':
  The node to be removed is not a child of this node.

For React engineers, that stack is a specific kind of footgun: React's reconciler is trying to unmount a DOM node and the parent it expects doesn't contain that child anymore. Something moved the node out from under React's feet. Usually that means a browser extension or another script is mutating the DOM directly, outside React's control.

We just couldn't reproduce it internally. The client who reported it most consistently was Altezia, and their bug report had a quiet detail buried in a screenshot: their Chrome DevTools UI was in French. Their Chrome itself was set to French, but our dashboard is in English.

That's what cracked it. Chrome's built-in auto-translate feature, when it sees an English page in a French Chrome session, does exactly what the bug needed: it wraps every text node in a <font> tag to translate it. React's Fiber tree still holds references to the original text nodes. The next time React tries to unmount one of them on any re-render (sort change, panel switch, message streaming, anything), the original parent doesn't contain that child anymore. Crash. White screen.

This is a known React issue, open since 2017. It also fires with Grammarly, Dark Reader, Stylus, and any other browser extension that mutates DOM outside React's control. It's the kind of bug you cannot reproduce in-house unless you have one of those triggers actively running on the page, which is why it took external user logs to identify.

The two layer fix

We added two layers of defense. The first prevents the bug from firing at all:

<html lang="en" translate="no">
<meta name="google" content="notranslate" />

Both signals tell Chrome (and other translators) to leave the page alone. The user sees the dashboard in English, which is fine because the product is in English and there's no business case for auto-translating a developer-facing UI line by line. React's tree stays intact. The crash trigger is gone.

The second layer is a defensive net for everything else that could still cause a white screen, now or later. A top-level <ErrorBoundary> now wraps the entire app. If anything crashes the React tree from any cause (a future bug, a different browser extension, a third-party script), the user sees a recovery card with a "Reload" button instead of a blank page. The card surfaces a contextual hint when the caught error contains "removeChild," nudging the user to check whether they have a translator or DOM-mutating extension active.

The combination is belt and braces. The notranslate signals handle the known cause. The error boundary handles unknown causes by failing visibly and recoverably, instead of disappearing into a blank tab.

Two history panel cleanups while we were in there

A couple of smaller fixes shipped in the same release because they were rough edges in the same general neighborhood (the conversation history panel on the right side of the chat).

Empty user bubbles are gone. Some user-aligned message bubbles in the history were rendering with nothing inside them, just the timestamp and the cyan border. The cause: in the Anthropic SDK protocol, every assistant tool call is followed by a synthetic "user" turn that only contains the tool result block. There's no actual user text. The history panel was passing these through to the renderer, which correctly produced an empty bubble. The filter now skips them, matching the same logic the live chat already uses.

System messages render properly. A Twilio Phone Call Ended message in the history used to dump the full backend payload verbatim: the transcript path, the how-to-read-the-transcript instructions, the whole pavé. Three hundred lines of text that was meant for the AI agent to parse, not for human eyes. Same thing for voice calls and email task notifications. The history now compresses these the same way the live chat does: a red Twilio glyph plus "Call ended (5m) - +972…", a phone icon plus "Call ended" for EE voice calls, a mail icon plus "New email task" for inbound mail. Same regexes, same visual treatment, history matches what you actually saw in the conversation.

Why this kind of release matters

This is not a flashy release. There's no new feature on the dashboard, no new integration, no new AI capability. But the white screen bug had been silently eroding trust for a small number of users, and tracking down a Heisenbug that only fires when a third-party browser feature is active is the kind of work that doesn't show up in any roadmap but quietly raises the floor on what the product feels like.

The conversation history panel cleanups are similar. Nobody asked for them in particular. They were just a couple of rough edges that made the panel feel less polished than the rest of the product. Fixing them in the same release as the white screen made sense because the panel rewrite touched some of the same code paths.

Want to test the most advanced AI employees? Try it here: https://Geta.Team

Read more