grafana/k6 · error

setting viewport size to %s: %w

Error message

setting viewport size to %s: %w

What it means

When an element is larger than the viewport, elementHandle.screenshot() first grows the viewport to max(viewport, boundingBox) via setViewportSize (Emulation.setDeviceMetricsOverride). This error wraps that CDP call failing, and includes the attempted size.

Source

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

	if err != nil {
		return nil, fmt.Errorf("node is either not visible or not an HTMLElement: %w", err)
	}
	if bbox.Width <= 0 {
		return nil, fmt.Errorf("node has 0 width")
	}
	if bbox.Height <= 0 {
		return nil, fmt.Errorf("node has 0 height")
	}

	var overriddenViewportSize *Size
	fitsViewport := bbox.Width <= viewportSize.Width && bbox.Height <= viewportSize.Height
	if !fitsViewport { //nolint:nestif
		overriddenViewportSize = Size{
			Width:  math.Max(viewportSize.Width, bbox.Width),
			Height: math.Max(viewportSize.Height, bbox.Height),
		}.enclosingIntSize()
		if err := h.frame.page.setViewportSize(overriddenViewportSize); err != nil {
			return nil, fmt.Errorf("setting viewport size to %s: %w",
				overriddenViewportSize, err)
		}
		err = h.waitAndScrollIntoViewIfNeeded(h.ctx, false, true, opts.Timeout)
		if err != nil {
			return nil, fmt.Errorf("scrolling element into view: %w", err)
		}
		bbox, err = h.boundingBox()
		if err != nil {
			return nil, fmt.Errorf("node is either not visible or not an HTMLElement: %w", err)
		}
		if bbox.Width <= 0 {
			return nil, fmt.Errorf("node has 0 width")
		}
		if bbox.Height <= 0 {
			return nil, fmt.Errorf("node has 0 height")
		}
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Stabilize the page before capture (await goto, waitForLoadState, no concurrent close).
  2. Retry the element screenshot once — transient emulation errors often clear.
  3. Set an initial viewport large enough to contain the element so no resize is needed.
  4. If sizes are extreme, capture with page.screenshot({fullPage:true}) or clip instead of element screenshot.

Example fix

// before
await page.$('.wide-table').then(el => el.screenshot({ path: 't.png' })); // element >> viewport, racing load

// after
const p = await browser.newPage({ viewport: { width: 1920, height: 2400 } });
await p.goto(url); await p.waitForLoadState('load');
await (await p.$('.wide-table')).screenshot({ path: 't.png' });
Defensive patterns

Strategy: try-catch

Validate before calling

const bb = await locator.boundingBox();
const fits = bb && bb.width <= 1280 && bb.height <= 720; // compare with your viewport; resize upfront if not

Try / catch

try { await el.screenshot({ path: 'e.png' }); }
catch (e) { if (String(e).includes('setting viewport size')) { /* wait for idle page, retry once */ } else throw e; }

Prevention

When it happens

Trigger: elementHandle.screenshot() on an element wider/taller than the viewport while the page is closing/navigating, the renderer is gone, or device-metrics emulation is in a bad state; also context cancellation during k6 teardown.

Common situations: Screenshotting full-width tables/long sections racing navigation; browser crash under load; oversized elements (huge data grids) hitting chrome's device-metrics limits.

Related errors


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