grafana/k6 · error
node has 0 width
Error message
node has 0 width
What it means
Hard guard in element screenshots: after computing the element's bounding box, its width is <= 0, so there is nothing to capture. The element exists and has a box, but it renders with zero width (height may be fine). Zero-size captures also crash some Chromium versions, hence the explicit check.
Solutions
- Verify computed width in DevTools; fix the CSS (min-width) or wait for content to expand the element.
- Wait for images/fonts: await page.waitForLoadState('networkidle') or wait for a size-bearing child.
- If capturing a visual, screenshot the parent container that has non-zero size instead.
- Set an explicit width on the element in test setup.
Example fix
// before
await page.$('.icon-host').screenshot({ path: 'i.png' }); // host is 0px wide
// after
await page.$('.icon-wrapper').screenshot({ path: 'i.png' }); // sized container
// or CSS: .icon-host { min-width: 32px; } Defensive patterns
Strategy: validation
Validate before calling
const box = await handle.boundingBox();
if (!box || box.width <= 0) throw new Error(`element width is ${box ? box.width : 'unknown'}; not capturable`); Type guard
const hasNonZeroWidth = async (h) => {
const b = await h.boundingBox();
return !!b && b.width > 0;
}; Prevention
- Check getComputedStyle width or boundingBox before capturing.
- Set min-width on empty hosts (icon wrappers, spacers).
- Screenshot a sized parent container instead of zero-width hosts.
When it happens
Trigger: await elementHandle.screenshot() on elements styled with width: 0 (or content collapsed by CSS: absolute positioning off-viewport, flex/grid item shrunk to 0, whitespace stripped), or an element whose content has not laid out yet (fonts/images not loaded).
Common situations: Screenshotting skeleton loaders or icons rendered via ::before only (host has 0 width); collapsed flex children; elements measured before web fonts/images expand them; responsive layouts under a narrow emulated viewport.
Related errors
- node has 0 height
- getting original viewport size
- node is either not visible or not an HTMLElement
- scrolling element into view
- capturing screenshot
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/100e946c6efaf963.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/screenshotter.go:307
) (buf []byte, err error) {
format := opts.Format
viewportSize, err := s.originalViewportSize(h.frame.page)
if err != nil {
return nil, fmt.Errorf("getting original viewport size: %w", err)
}
originalSize := h.frame.page.emulatedSize
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")
}
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()
defer func() {
if restoreErr := s.restoreViewport(h.frame.page, originalSize); restoreErr != nil {
err = errors.Join(err, fmt.Errorf("restoring viewport: %w", restoreErr))
}
}()
if err := h.frame.page.setViewportSize(s.ctx, overriddenViewportSize); err != nil {
return nil, fmt.Errorf("setting viewport size to %s: %w",View on GitHub (pinned to 3fcf5388d7)