grafana/k6 · error

scrolling element into view: %w

Error message

scrolling element into view: %w

What it means

Thrown by the k6 browser module's ElementHandle.scrollIntoViewIfNeeded(). It wraps the failure of the internal waitAndScrollIntoViewIfNeeded action, which first waits for the element to be in the 'visible' and 'stable' states (with retry), then evaluates element.scrollIntoViewIfNeeded(true) in the page. It fails when the element never becomes actionable before the timeout, is hidden or detached, or the in-page evaluation errors out.

Source

Thrown at internal/js/modules/k6/browser/common/element_handle.go:1407

	)
	defer span.End()

	span.SetAttributes(attribute.String("screenshot.path", opts.Path))

	s := newScreenshotter(spanCtx, sp, h.logger)
	buf, err := s.screenshotElement(h, opts)
	if err != nil {
		return nil, spanRecordErrorf(span, "taking screenshot of elementHandle: %w", err)
	}

	return buf, err
}

// ScrollIntoViewIfNeeded scrolls element into view if needed.
func (h *ElementHandle) ScrollIntoViewIfNeeded(opts *ElementHandleBaseOptions) error {
	err := h.waitAndScrollIntoViewIfNeeded(h.ctx, opts.Force, opts.NoWaitAfter, opts.Timeout)
	if err != nil {
		return fmt.Errorf("scrolling element into view: %w", err)
	}

	applySlowMo(h.ctx)

	return nil
}

// SelectOption selects the options matching the given values.
func (h *ElementHandle) SelectOption(values []any, opts *ElementHandleBaseOptions) ([]string, error) {
	selectOption := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
		return handle.selectOption(apiCtx, values)
	}
	selectOptionAction := h.newAction(
		[]string{}, selectOption, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
	)
	selectedOptions, err := call(h.ctx, selectOptionAction, opts.Timeout)
	if err != nil {
		return nil, fmt.Errorf("selecting options: %w", err)

View on GitHub (pinned to 01ffac6f24)

Solutions

  1. Wait for the element to be actionable first: await el.waitForElementState('visible', { timeout: '10s' }) or use a locator/page.waitForSelector before scrolling.
  2. Re-query the handle after navigation or rerender: const el = await page.$(selector) again, since old handles go stale.
  3. Pass a larger timeout: el.scrollIntoViewIfNeeded({ timeout: '60s' }) or raise the browser-level default via options timeouts in the k6 browser options.
  4. Disable CSS animations/transitions in the page under test so the 'stable' check passes immediately.
  5. Pass { force: true } to skip the actionability wait if you know the element exists but never reports stable.

Example fix

// before
const el = await page.$('#footer');
await el.scrollIntoViewIfNeeded(); // fails: element hidden/unstable until late render

// after
const el = await page.waitForSelector('#footer', { state: 'visible', timeout: '30s' });
await el.scrollIntoViewIfNeeded({ timeout: '30s' });
Defensive patterns

Strategy: try-catch

Validate before calling

const visible = await el.isVisible().catch(() => false);
if (visible) {
  await el.scrollIntoViewIfNeeded({ timeout: '30s' });
}

Try / catch

try {
  await el.scrollIntoViewIfNeeded({ timeout: '30s' });
} catch (e) {
  if (String(e).includes('timed out') || String(e).includes('not attached')) {
    el = await page.waitForSelector(sel, { state: 'visible', timeout: '30s' });
    await el.scrollIntoViewIfNeeded({ timeout: '30s' });
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling elementHandle.scrollIntoViewIfNeeded() on an element that is display:none or visibility:hidden; on an element still animating so the 'stable' check never passes; on a handle whose node was removed by an SPA rerender; with the default timeout (30s) too short on slow CI machines.

Common situations: SPA frameworks (React/Vue) re-rendering and detaching the node mid-action; CSS transitions keeping the element 'unstable'; pages with lazy-rendered content below the fold; CI environments where CDP round-trips are slow and the default timeout expires.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/1e2d8ba3e9f540d7. Report an issue: GitHub.