Browser tools: a backgrounded Browser pane silently freezes requestAnimationFrame, making healthy pages look broken

Status Closed — duplicate
Maintainer reply None cached
Activity 1 comment · opened Aug 7, 2026 · closed Aug 25, 2026

Summary

When the Browser pane is not visible, Chrome backgrounds the renderer and requestAnimationFrame callbacks stop firing. Any page whose mount or content depends on rAF then never finishes rendering — but the browser tools report this as an empty DOM with no errors, which is indistinguishable from a genuine application bug.

The result is that the agent confidently starts debugging code that is completely fine. In my experience this happens several times a day and has cost hours of wall-clock time and a large number of tokens across many sessions. It is the single most expensive false signal I hit with the browser tooling.

Symptom signature

All of these are true at once, which is exactly what a real breakage looks like:

  • Every content container has height: 0 and contains only its framework placeholder (for Observable Framework: <!--:cellid:-->).
  • No error elements anywhere in the DOM.
  • read_console_messages (including onlyErrors: true) reports nothing.
  • Fetching every module and asset by hand returns 200.
  • Importing those same modules in the page via javascript_tool and calling them by hand works perfectly and produces correct output.
  • The dev server logs show the page served and its data loaders completed.

Root cause

document.visibilityState === "hidden" / document.hidden === true for the pane's page. Chrome pauses requestAnimationFrame in backgrounded renderers, so anything scheduled through rAF never runs. This includes framework mount paths and ordinary UI animation code.

Reproduction

  1. preview_start, then navigate to a page that uses requestAnimationFrame (Observable Framework pages qualify out of the box).
  2. Do not take a screenshot.
  3. Inspect with read_page or javascript_tool → empty containers, zero errors.
  4. Take computer{action: "screenshot"} → the renderer wakes and the page resolves within a few seconds.

Step 4 is why "just take a screenshot" appears to randomly fix things: it is the only tool in the set that reliably forces a paint. That accidental workaround masks the real behaviour and makes the bug feel nondeterministic.

Affects both the built-in Browser pane tools and the Claude-in-Chrome tools.

Why it is so costly

The failure mode actively rewards the wrong diagnosis:

  • Because nothing errors, the agent concludes the page silently hung and goes looking for a hang in application code.
  • Because the same page renders correctly when driven by hand, the agent concludes the framework's cell/mount layer is broken.
  • Because it reproduces after a reload, the agent concludes the dev server is wedged and restarts it — which fixes nothing and, for a large site, triggers a multi-minute cache rebuild that makes the next check look broken too, reinforcing the misdiagnosis.

I went through that entire sequence today, including needlessly killing a dev server that had been healthy the whole time.

The one reliable tell is that it reproduces on every page of the site, including trivial pages unrelated to any recent change — but that requires already suspecting the environment, which is the thing the tools give no hint of.

Suggested fixes, roughly in order of value

  1. Surface it. Have read_page, get_page_text, find, and javascript_tool include a warning in their result when document.visibilityState === "hidden" at call time — e.g. "the page is backgrounded; rAF-driven rendering is paused, take a screenshot or bring the pane to front before concluding the page is broken." This alone would eliminate the misdiagnosis.
  2. Prevent it. Launch the pane's browser with --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-renderer-backgrounding, and/or force the lifecycle state via CDP Page.setWebLifecycleState({state: "active"}) so a hidden pane still paints.
  3. Wake automatically. Make navigate and the DOM-reading tools force a frame the way screenshot implicitly does, so inspection is not silently sampling a frozen page.

Any one of the three would fix it; (1) is cheap and would have saved me every one of these hours.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗