grafana/k6 · error

capturing screenshot

Error message

capturing screenshot: %w

What it means

The core screenshot failure: the CDP Page.captureScreenshot command (with any accumulated quality/format/clip options) returned an error. Everything before it (background override, layout metrics, clip computation) succeeded; the capture itself failed. The wrapped error carries the CDP reason, most commonly 'target closed' after a renderer crash.

Solutions

  1. Read the wrapped CDP error: 'target closed'/'session detached' → renderer died or page closed; fix memory/shm (--disable-dev-shm-usage, bigger container) or guard with page.isClosed().
  2. Retry the screenshot once after a wait — navigation races are often transient.
  3. For huge full-page captures, cap dimensions by clipping or reduce viewport to avoid renderer OOM.
  4. Launch Chromium with --disable-gpu / --disable-dev-shm-usage in containers.
  5. Avoid screenshotting while triggering navigations in the same tick.

Example fix

// before (bare chromium, small shm container)
await page.screenshot({ path: 'big.png', fullPage: true });

// after
const browser = chromium.launch({
  args: ['--disable-dev-shm-usage', '--disable-gpu'],
});
await page.screenshot({ path: 'big.png', fullPage: true });
Defensive patterns

Strategy: retry

Validate before calling

if (page.isClosed()) throw new Error('page closed before screenshot');
await page.waitForLoadState('load');

Try / catch

try {
  buf = await page.screenshot({ path: 's.png' });
} catch (e) {
  if (/capturing screenshot/i.test(String(e)) && !/target closed/i.test(String(e))) {
    await page.waitForTimeout(500);
    buf = await page.screenshot({ path: 's.png' });
  } else throw e; // target closed: renderer/page gone, no point retrying
}

Prevention

When it happens

Trigger: page.screenshot() / elementHandle.screenshot() when the renderer process crashes (OOM), the page navigates away mid-capture, the target is closed by the script or teardown, or Chrome hits an internal error producing the image (e.g. zero-size capture on some GPU-less headless setups).

Common situations: Docker/CI Chrome crashes from small /dev/shm or memory limits on large full-page screenshots; screenshotting during redirect churn; GPU rendering issues in headless containers requiring software rendering flags.

Related errors


AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-09-20). Data as JSON: /api/errors/6427a8d503899270. Report an issue: GitHub.

Appendix: source

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

	scale := 1.0
	if viewport != nil {
		scale = visualViewportScale
	}
	clip = &cdppage.Viewport{
		X:      doc.X,
		Y:      doc.Y,
		Width:  doc.Width,
		Height: doc.Height,
		Scale:  scale,
	}
	if clip.Width > 0 && clip.Height > 0 {
		capture = capture.WithClip(clip)
	}

	// Capture screenshot
	buf, err = capture.Do(cdp.WithExecutor(s.ctx, sess))
	if err != nil {
		return nil, fmt.Errorf("capturing screenshot: %w", err)
	}

	// 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

View on GitHub (pinned to 3fcf5388d7)