Skip to content

fix(playwright): keep recording when a single screenshot fails - #119

Open
totigm wants to merge 1 commit into
mainfrom
fix/capture-tolerates-dropped-frames
Open

totigm wants to merge 1 commit into
mainfrom
fix/capture-tolerates-dropped-frames

Conversation

@totigm

@totigm totigm commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Recording a real site could fail outright and report only this:

Error: No frames were captured. The recording window may have been too short,
or the page may not have rendered any frames before the callback completed.

Neither suggestion was the cause. The actual cause was one screenshot failing.

What was happening

packages/playwright/src/recording/capture.ts treated any page.screenshot() rejection as terminal — set stopped = true and return. So a single transient error meant zero frames from that point on, and if it happened early, zero frames at all. The export then failed with a message describing two things that had not gone wrong.

A transient Page.captureScreenshot: Unable to capture screenshot is ordinary on a page under load; a heavy animation or a font swap is enough to make Chromium miss one.

The tell was eleven lines up, where a failed frame write already did the right thing:

// A single failed write drops one frame but doesn't poison the queue

Writes tolerated failure; screenshots did not. The two paths now agree.

Behaviour now

Case Before After
Transient screenshot error recording lost frame dropped, recording continues
Page closed mid-capture stops, with a warning stops, silently — an expected end, not a fault
Persistent failure stops on the first one stops after 10 consecutive, with a clear message
Warning volume once, then dead once per run of failures, not once per frame

The failure counter resets on every success, so scattered misses across a long recording never accumulate into a false give-up.

Verification

5 unit tests driving the loop with scripted screenshot behaviour: transient recovery, warn-once, silent stop on a closed page, the consecutive cap actually bounding the call count, and the counter resetting on success.

The real check is the page that found it. https://humanjs.dev reproduced the failure every time and now records through it:

humanjs capture: screenshot failed, dropping frame: ... Unable to capture screenshot
OK — 6 actions, 7946ms      (9.7 MB GIF written)

Whole suite green: lint, typecheck (10/10), test (9/9), build (7/7), check:exports (13/13).

Found while dogfooding #118.

The capture loop treated any page.screenshot() rejection as terminal:
it stopped, captured nothing further, and the export then died with
"No frames were captured". A transient Page.captureScreenshot protocol
error is ordinary on a page under load -- a heavy animation or a font
swap is enough -- so recording a real site could fail outright.

Odder still, a failed frame *write* eleven lines up already did the
right thing: drop the frame, keep the queue moving. The two paths now
agree.

A closed page still stops immediately, since there is nothing left to
shoot, and ten consecutive failures still give up rather than spinning
at the frame rate forever. The warning fires once per run of failures
instead of once per frame.

Found by pointing the new CLI at humanjs.dev, which reproduced it every
time; the same page now records through the dropped frame.
@vercel

vercel Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
humanjs Ready Ready Preview Sep 1, 2026 1:31pm UTC

This branch was successfully deployed

1 active deployment
Preview — 5de7cfe2 Deployed Sep 1, 2026 by vercel[bot]
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