grafana/k6 · error

getting layout metrics for screenshot

Error message

getting layout metrics for screenshot: %w

What it means

Thrown by getViewPortDimensions when the CDP Page.getLayoutMetrics call fails; the screenshotter needs the CSS visual viewport (scale, pageX, pageY) to compute full-page clip geometry. Notably, a nil cssVisualViewport is handled gracefully (warns and falls back to defaults), so this error means the CDP call itself errored, not a nil metric.

Solutions

  1. Check the wrapped CDP error for 'target closed' — fix renderer stability (memory, --disable-dev-shm-usage) or screenshot before teardown.
  2. Take the screenshot after the page reaches a stable lifecycle state.
  3. Retry once for navigation races.
  4. Reduce screenshot frequency in long runs if the browser is destabilizing.

Example fix

// before
await page.screenshot({ path: 'full.png', fullPage: true }); // mid-redirect

// after
await page.waitForLoadState('load');
await page.screenshot({ path: 'full.png', fullPage: true });
Defensive patterns

Strategy: retry

Validate before calling

await page.waitForLoadState('load'); // stable page before fullPage/clip capture

Try / catch

try {
  await page.screenshot({ fullPage: true, path: 'f.png' });
} catch (e) {
  if (/getting layout metrics/i.test(String(e)) && !/target closed/i.test(String(e))) {
    await page.waitForTimeout(500);
    await page.screenshot({ fullPage: true, path: 'f.png' });
  } else throw e;
}

Prevention

When it happens

Trigger: Any screenshot needing viewport metrics (fullPage or clip) where the CDP session is broken: page/target closed mid-screenshot, renderer crash, or navigation racing the metrics call.

Common situations: Full-page screenshots in memory-constrained containers where the renderer dies; screenshotting while a page is being redirected or closed; flaky CDP connections in long test runs.

Related errors


AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18). Data as JSON: /api/errors/ac7b385acdd738ee. Report an issue: GitHub.

Appendix: source

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

	// Save screenshot capture to file
	if path != "" {
		if err := s.persister.Persist(s.ctx, path, bytes.NewBuffer(buf)); err != nil {
			return nil, fmt.Errorf("persisting screenshot: %w", err)
		}
	}

	return buf, nil
}

func getViewPortDimensions(ctx context.Context, sess session, logger *log.Logger) (float64, float64, float64, error) {
	visualViewportScale := 1.0
	visualViewportPageX, visualViewportPageY := 0.0, 0.0

	// Add clip region
	//nolint:dogsled
	_, _, _, _, cssVisualViewport, _, err := cdppage.GetLayoutMetrics().Do(cdp.WithExecutor(ctx, sess))
	if err != nil {
		return 0, 0, 0, fmt.Errorf("getting layout metrics for screenshot: %w", err)
	}

	// we had a null pointer panic cases, when visualViewport is nil
	// instead of the erroring out, we fallback to defaults and still try to do a screenshot
	if cssVisualViewport != nil {
		visualViewportScale = cssVisualViewport.Scale
		visualViewportPageX = cssVisualViewport.PageX
		visualViewportPageY = cssVisualViewport.PageY
	} else {
		logger.Warnf(
			"Screenshotter::screenshot",
			"chrome browser returned nil on page.getLayoutMetrics, falling back to defaults for cssVisualViewport "+
				"(scale: %v, pageX: %v, pageY: %v)."+
				"This is non-standard behavior, if possible please report this issue (with a reproducible script) "+
				"to the https://github.com/grafana/k6/issues/new.",
			visualViewportScale, visualViewportPageX, visualViewportPageY,
		)
	}

View on GitHub (pinned to 3fcf5388d7)