Skip to content

Fix screenshot timing out when the target page is not in the foreground - #55

Open
goeric wants to merge 1 commit into
simonw:mainfrom
goeric:fix/activate-target-before-capture
Open

Fix screenshot timing out when the target page is not in the foreground#55
goeric wants to merge 1 commit into
simonw:mainfrom
goeric:fix/activate-target-before-capture

Conversation

@goeric

@goeric goeric commented Jul 27, 2026

Copy link
Copy Markdown

Summary

rodney screenshot fails with context deadline exceeded whenever the page it
targets is not the browser's foreground target:

rodney open https://www.epicured.com/
rodney screenshot a.png      # works
rodney newpage <other url>
rodney page 1                # switch back
rodney url                   # correct page
rodney screenshot b.png      # error: screenshot failed: context deadline exceeded

Root cause

rodney's "active page" is only an index in its own state file (active_page).
The browser is never told about it, so after rodney page N the foreground
target is still whichever page was opened last. cmdPage wrote the index and
nothing else — Activate/bringToFront appeared nowhere in the codebase.

DOM and JS commands don't care: they read a hidden target perfectly well, which
is why url, js and text all keep reporting the switched-to page correctly.
But a backgrounded target has no compositor producing frames, so
Page.captureScreenshot waits for one that never arrives.

Page size is a red herring. Measured: a heavy page captures in 0.23s when
it is in the foreground, while a backgrounded example.com times out after 30s.
What decides it is foreground, not weight — the reported "heavy page" correlation
was a confound, because the heavy page happened to be the backgrounded one.

screenshot-el is affected too, and worse: rod's element stability wait ignores
the page timeout, so a hidden target hangs for over eight minutes rather than
30 seconds. pdf is unaffected — printToPDF re-renders and needs no frame.

Fix

  • cmdPage switches the browser as well as the index, so the page a caller just
    selected is the one being rendered.
  • cmdScreenshot and cmdScreenshotEl raise their target before capturing, so a
    state file that has drifted out of sync with the browser (page opened by
    window.open, foreground page closed) cannot wedge a capture.

Not a regression from the crash fixes

It reproduces identically on the pre-crash-fix binary with --single-process and
old headless, so it is pre-existing and unrelated to #54 or to extension mode.

Verification

scenario before after
1 page, heavy foreground 1s OK 1s OK
2 pages, heavy backgrounded 30s timeout 1s, 5.6 MB
2 pages, light backgrounded 30s timeout 0s OK
screenshot-el, backgrounded >8 min hang 0s OK
reported repro, extension mode fails at step b all three captures OK

Three regression tests added. Verified they genuinely catch the bug: with
bringToFront neutered they fail in 51s total (0.08s / 20.06s / 30.07s);
with the fix they pass in 3.4s. The element test bounds its own wait so a
regression fails that one test rather than panicking the suite ten minutes later,
which is what an unbounded version did.

go build, go vet and the full go test ./... suite pass.

🤖 Generated with Claude Code

"rodney screenshot" fails with "context deadline exceeded" whenever the
page it targets is not the browser's foreground one:

    rodney open <heavy page>
    rodney screenshot a.png      # works
    rodney newpage <other url>
    rodney page 1                # back to the heavy page
    rodney screenshot b.png      # context deadline exceeded

rodney's "active page" is only an index in its own state file. The
browser is never told about it, so after "rodney page N" the foreground
target is still whichever page was opened last. DOM and JS commands do
not care -- they read a hidden target perfectly well, which is why url,
js and text all keep reporting the switched-to page correctly -- but a
backgrounded target has no compositor producing frames, and
Page.captureScreenshot waits for one that never arrives.

Page weight is a red herring: a heavy page captures in 0.23s when it is
in the foreground, while a backgrounded example.com times out. What
decides it is foreground, not size. Element capture is affected too, and
worse: rod's stability wait ignores the page timeout, so screenshot-el
on a hidden target hangs for over eight minutes rather than 30 seconds.

cmdPage now switches the browser as well as the index, and both capture
commands raise their target first, so a state file that has drifted out
of sync with the browser cannot wedge a capture.

Not a regression from the crash fixes: it reproduces identically on the
pre-crash-fix binary with --single-process and old headless.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant