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
- Wait for the element to be actionable first: await el.waitForElementState('visible', { timeout: '10s' }) or use a locator/page.waitForSelector before scrolling.
- Re-query the handle after navigation or rerender: const el = await page.$(selector) again, since old handles go stale.
- Pass a larger timeout: el.scrollIntoViewIfNeeded({ timeout: '60s' }) or raise the browser-level default via options timeouts in the k6 browser options.
- Disable CSS animations/transitions in the page under test so the 'stable' check passes immediately.
- 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
- Always acquire handles via waitForSelector with a state, never bare page.$ right before an action.
- Do not cache ElementHandles across clicks that trigger rerenders or navigation.
- Set an explicit timeout on every action instead of relying on the 30s default in CI.
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
- selecting text: %w
- waiting for element state: %w
- tapping element: %w
- typing text %q: %w
- waiting for element state %q: %w
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/1e2d8ba3e9f540d7.
Report an issue: GitHub.