grafana/k6 · error
node has 0 width
Error message
node has 0 width
What it means
elementHandle.screenshot() refuses to capture when the element's bounding box has width <= 0. The element has a layout box but renders with zero width (first check, before any viewport resizing).
Source
Thrown at internal/js/modules/k6/browser/common/screenshotter.go:289
func (s *screenshotter) screenshotElement(h *ElementHandle, opts *ElementHandleScreenshotOptions) ([]byte, error) {
format := opts.Format
viewportSize, originalViewportSize, err := s.originalViewportSize(h.frame.page)
if err != nil {
return nil, fmt.Errorf("getting original viewport size: %w", 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")
}
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 {View on GitHub (pinned to 93accf6570)
Solutions
- Wait until the element has size: poll await locator.boundingBox() until width > 0, or waitFor({state:'visible'}) plus a settled state.
- Give the element an explicit width via CSS if it is a container you control.
- Capture later in the lifecycle (after data render/charts drawn).
- If zero-width is expected, screenshot the page with a clip around the area instead of the element.
Example fix
// before
await page.$('.drawer').then(el => el.screenshot({ path: 'd.png' })); // mid-animation width 0
// after
const drawer = page.locator('.drawer');
await page.waitForFunction(() => document.querySelector('.drawer').getBoundingClientRect().width > 0);
await drawer.screenshot({ path: 'd.png' }); Defensive patterns
Strategy: validation
Validate before calling
const bb = await locator.boundingBox();
if (!bb || bb.width <= 0) throw new Error('element has zero width; wait for it to render'); Type guard
function hasPositiveWidth(bb) { return bb != null && Number.isFinite(bb.width) && bb.width > 0; } Try / catch
try { await el.screenshot({ path: 'e.png' }); }
catch (e) { if (String(e).includes('node has 0 width')) { /* wait for width>0 then retry */ } else throw e; } Prevention
- Wait for content (data, images) that gives the element width.
- Avoid capturing mid-animation drawers/progress bars.
- Prefer locator.screenshot() so you can boundingBox() first.
When it happens
Trigger: Elements with CSS width:0 (collapsed), zero-size inline elements, containers whose children are absolutely positioned so the parent has no intrinsic width, or elements in a display:grid/flex context that collapsed to 0.
Common situations: Empty data containers before async data arrives; icon-only elements sized only by content that hasn't loaded; elements animated from width:0 (drawers, progress bars) captured mid-animation.
Related errors
- node has 0 height
- parsing element handle screenshot options: %w
- getting original viewport size: %w
- scrolling element into view: %w
- node is either not visible or not an HTMLElement: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/100e946c6efaf963.
Report an issue: GitHub.