grafana/k6 · error
waiting for element state: %w
Error message
waiting for element state: %w
What it means
Actionability stage of pointer actions (non-force mode): waitForElementState(['visible','stable','enabled']) failed after the initial scroll. The injected waitForElementStates call either timed out (element never satisfies all three states) or returned a DOM error (element detached, not an element). This is the classic 'element is not actionable' failure for click/hover/tap.
Source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1712
// 4. Enabled
// 5. Receives events
pointerFn := func(apiCtx context.Context, sopts *ScrollIntoViewOptions) (res any, err error) {
// We need to scroll the element into view first, otherwise we can
// end up in a situation where the element is not in the correct state
// (visible and stable, but could be enabled).
err = h.scrollRectIntoViewIfNeeded(apiCtx, nil)
if err != nil {
return nil, fmt.Errorf("scrolling element into view: %w", err)
}
// Check if we should run actionability checks
if !opts.Force {
// As mentioned above, if we didn't scroll first, we could end
// up stuck waiting indefinitely for the element to be in the
// correct state.
states := []string{"visible", "stable", "enabled"}
if _, err = h.waitForElementState(apiCtx, states, opts.Timeout); err != nil {
return nil, fmt.Errorf("waiting for element state: %w", err)
}
}
// Decide position where a mouse down should happen if needed by action
p := opts.Position
// Change scrolling action depending on the scrolling options
if sopts == nil {
var rect *dom.Rect
if p != nil {
rect = &dom.Rect{X: p.X, Y: p.Y}
}
err = h.scrollRectIntoViewIfNeeded(apiCtx, rect)
} else {
_, err = h.eval(
apiCtx,
evalOptions{forceCallable: true, returnByValue: false},
js.ScrollIntoView,View on GitHub (pinned to 93accf6570)
Solutions
- Increase the action timeout: el.click({ timeout: '30s' })
- If the checks themselves are the blocker (e.g. deliberate animation), use force: true to skip the state wait
- Disable animations in the test environment or wait for a stable app state before acting
- For disabled controls, wait for the enabling condition (el.waitForElementState('enabled')) instead of hammering click
Example fix
// before
page.$('#save').click(); // button disabled during autosave
// after
const save = page.waitForSelector('#save', { state: 'visible' });
save.waitForElementState('enabled', { timeout: '20s' });
save.click(); Defensive patterns
Strategy: try-catch
Validate before calling
const el = page.waitForSelector('#save', { state: 'visible' });
el.waitForElementState('stable', { timeout: '10s' });
el.waitForElementState('enabled', { timeout: '10s' });
el.click(); Try / catch
try {
el.click({ timeout: '30s' });
} catch (e) {
const msg = String(e);
if (msg.includes('waiting for element state')) {
if (msg.includes('enabled')) throw new Error('control stayed disabled: ' + msg);
el.click({ force: true }); // deliberate skip of state checks
} else {
throw e;
}
} Prevention
- Disable non-essential animations in the test environment
- Wait for enabled state instead of retrying clicks in a loop
- Give the action a timeout sized to the app's longest transition
When it happens
Trigger: Element continuously animating (CSS transitions, carousels) so 'stable' never holds; disabled buttons failing 'enabled'; element toggling visibility on hover/jitter; timeout too short for the app's transitions; element detached mid-wait.
Common situations: Buttons with loading spinners that keep re-layouting; sticky elements recalculating position; disabled submit buttons gated on network validation that fails; fast default timeouts against slow staging environments.
Related errors
- clicking on element: %w
- double clicking on element: %w
- filling element: %w
- hovering on element: %w
- pressing %q on element: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/ac108059fdfbef8c.
Report an issue: GitHub.