grafana/k6 · error

getting viewport dimensions: %w

Error message

getting viewport dimensions: %w

What it means

Thrown when the screenshotter cannot read the viewport dimensions of a page whose CDP-assigned viewport is 0x0. It evaluates `() => ({width: window.innerWidth, height: window.innerHeight})` in the main frame and this CDP Runtime.evaluate call itself failed (the error is wrapped verbatim). This is a Chrome DevTools Protocol-level failure, not a size problem.

Source

Thrown at internal/js/modules/k6/browser/common/screenshotter.go:137

}

func (s *screenshotter) originalViewportSize(p *Page) (*Size, *Size, error) {
	originalViewportSize := p.viewportSize()
	viewportSize := originalViewportSize
	if viewportSize.Width != 0 || viewportSize.Height != 0 {
		return &viewportSize, &originalViewportSize, nil
	}

	opts := evalOptions{
		forceCallable: true,
		returnByValue: true,
	}
	result, err := p.frameManager.MainFrame().evaluate(s.ctx, mainWorld, opts, `
	() => (
		{ width: window.innerWidth, height: window.innerHeight }
	)`)
	if err != nil {
		return nil, nil, fmt.Errorf("getting viewport dimensions: %w", err)
	}

	var returnVal Size
	if err := convert(result, &returnVal); err != nil {
		return nil, nil, fmt.Errorf("unpacking window size: %w", err)
	}

	viewportSize.Width = returnVal.Width
	viewportSize.Height = returnVal.Height

	return &viewportSize, &originalViewportSize, nil
}

func (s *screenshotter) restoreViewport(p *Page, originalViewport *Size) error {
	if originalViewport != nil {
		return p.setViewportSize(originalViewport)
	}
	return p.resetViewport()

View on GitHub (pinned to 93accf6570)

Solutions

  1. Await navigation fully before screenshotting: await page.goto(url); await page.waitForLoadState('load');
  2. Ensure the page is still open — remove any page.close() that can race the screenshot.
  3. Retry the screenshot once after a short wait if the failure message contains 'Execution context was destroyed' or 'Target closed'.
  4. If the browser dies repeatedly, check container memory limits / chromium crash logs (renderer OOM shows up here).

Example fix

// before
const p = await browser.newPage();
const nav = p.goto(url); // not awaited
await p.screenshot({ path: 's.png' }); // evaluate can lose the context mid-navigation

// after
const p = await browser.newPage();
await p.goto(url);
await p.waitForLoadState('load');
await p.screenshot({ path: 's.png' });
Defensive patterns

Strategy: try-catch

Validate before calling

await page.goto(url);
await page.waitForLoadState('load');
// page must not be closed concurrently

Try / catch

try {
  await page.screenshot({ path: 's.png' });
} catch (e) {
  if (/Target closed|Execution context was destroyed|session closed/i.test(String(e))) {
    await sleep(500); await page.screenshot({ path: 's.png' }); // one retry
  } else { throw e; }
}

Prevention

When it happens

Trigger: page.setViewportSize was never applied / page has no emulated viewport, and during the evaluate: the page is navigating (execution context destroyed), the page/target was closed, the renderer crashed, or the screenshotter context was cancelled (test ending, iteration timeout).

Common situations: Calling page.screenshot() concurrently with page.goto() or page.reload(); screenshotting right before/after page.close(); browser process killed by OOM in a container; k6 iteration teardown racing the screenshot.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/ec54461e4567a704. Report an issue: GitHub.