grafana/k6 · error
hovering on element
Error message
hovering on element: %w
What it means
ElementHandle.hover() wraps the failure of a pointer action that scrolls the element into view, waits for it to be visible, stable, and able to receive pointer events, then moves the mouse to its center via the CDP Input domain. Timeouts on any of those waits, hit-test failures, or session errors get this prefix.
Solutions
- Hover the parent/menu trigger first, then hover the revealed child
- Wait for the element: await el.waitFor({ state: 'visible' }) before hovering
- Use force: true to skip actionability and hit testing: await el.hover({ force: true })
- Increase the timeout: await el.hover({ timeout: '60s' })
- Re-query the element handle if the page re-rendered
Example fix
// before
const sub = await page.$('.menu .submenu-item');
await sub.hover(); // submenu not open / parent not hovered
// after
await page.$('.menu .top-item').hover();
const sub = await page.$('.menu .submenu-item');
await sub.waitFor({ state: 'visible', timeout: '5s' });
await sub.hover(); Defensive patterns
Strategy: try-catch
Validate before calling
// Open the menu and wait for the child before hovering
await page.$('.menu .top-item').hover();
const child = await page.waitForSelector('.menu .submenu-item', { state: 'visible', timeout: '5s' });
await child.hover(); Try / catch
try {
await el.hover({ timeout: '10s' });
} catch (e) {
const msg = String(e.message);
if (/timed out|would receive the event|not stable/i.test(msg)) {
await el.hover({ force: true }); // skip actionability + hit test
} else if (/Could not find object|not attached/i.test(msg)) {
const fresh = await page.$(sel);
await fresh.hover();
} else throw e;
} Prevention
- Hover the parent trigger first when submenus only render on hover
- waitFor({ state: 'visible' }) before hover
- Disable animations in the test environment when possible to keep elements stable
When it happens
Trigger: Another element covers the target so the hit test fails ('other element would receive the event'); the element is hidden, zero-sized, or off-viewport; the element animates and never stabilizes; the handle is detached; the hover-capable parent is not hovered first so the child does not exist yet; the timeout option expires.
Common situations: Hover menus that only render after hovering the parent item; sticky headers/footers covering targets; banners and overlays; animation-heavy marketing pages; re-renders detaching the handle.
Related errors
- double clicking on element
- " " must be one of
- clickCount must be an integer, got
- clicking on element
- delay must be an integer, got
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/af156028f788e1ef.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:978
s, ok := v.(string)
if !ok {
return "", false, fmt.Errorf(
"getting attribute %q of element: unexpected type %T (expecting string)",
name, v,
)
}
return s, true, nil
}
// Hover scrolls element into view and hovers over its center point.
func (h *ElementHandle) Hover(opts *ElementHandleHoverOptions) error {
hover := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) {
return nil, handle.hover(apiCtx, p)
}
hoverAction := h.newPointerAction(hover, &opts.ElementHandleBasePointerOptions)
if _, err := call(h.ctx, hoverAction, opts.Timeout); err != nil {
return fmt.Errorf("hovering on element: %w", err)
}
applySlowMo(h.ctx)
return nil
}
// InnerHTML returns the inner HTML of the element.
func (h *ElementHandle) InnerHTML() (string, error) {
innerHTML := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return handle.innerHTML(apiCtx)
}
opts := NewElementHandleBaseOptions(h.DefaultTimeout())
innerHTMLAction := h.newAction(
[]string{}, innerHTML, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
)
v, err := call(h.ctx, innerHTMLAction, opts.Timeout)
if err != nil {View on GitHub (pinned to 3fcf5388d7)