grafana/k6 · error

waiting for states %v of element %q

Error message

waiting for states %v of element %q

What it means

waitForElementStates expects 'done', a bool, or an 'error:...' string from the injected script. Any other type produces this error. The message also misuses %q with a reflect.Type argument, so it renders like waiting for states [visible] of element %!q(*reflect.rtype=...). This wait backs every actionability check and the Is* helpers (isVisible, isChecked, ...).

Source

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

	opts := evalOptions{
		forceCallable: true,
		returnByValue: true,
	}
	result, err := h.evalWithScript(apiCtx, opts, fn, states, timeout.Milliseconds())
	if err != nil {
		return false, errorFromDOMError(err)
	}
	switch v := result.(type) {
	case string: // Either we're done or an error happened (returned as "error:..." from JS)
		if v == resultDone {
			return true, nil
		}
		return false, errorFromDOMError(v)
	case bool:
		return v, nil
	}

	return false, fmt.Errorf(
		"waiting for states %v of element %q", states, reflect.TypeOf(result))
}

// stepIntoFrame steps into an iframe/frame. Due to CORS, we need to perform this
// step outside of the browser (chromium). It returns the frame that it has stepped
// into and the selector to use within that frame.
func (h *ElementHandle) stepIntoFrame(
	apiCtx context.Context, parsedSelector *Selector, frameNavIndex int, opts *FrameWaitForSelectorOptions,
) (*Frame, string, error) {
	// Split selector at frame navigation boundary
	beforeFrame, afterFrame := h.splitSelectorAtFrame(parsedSelector, frameNavIndex)

	// Find the iframe element using the "before frame" selector
	iframeSelector := h.reconstructSelector(beforeFrame)

	iframeHandle, err := h.waitForSelector(apiCtx, iframeSelector, opts)
	if err != nil {
		return nil, "", fmt.Errorf("finding iframe with selector %q: %w", iframeSelector, err)

View on GitHub (pinned to 93accf6570)

Solutions

  1. Retry the action after the page settles and the element is re-located
  2. Upgrade to a clean matching k6 build
  3. Increase the timeout so waits don't race navigation
  4. Report with a minimal script if reproducible on a stock release
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await handle.click();
} catch (e) {
  if (String(e).includes('waiting for states')) {
    await (await page.waitForSelector(sel, { state: 'visible' })).click();
  } else { throw e; }
}

Prevention

When it happens

Trigger: Any element action (click, fill via its visible/enabled/editable preconditions) or isVisible()/isHidden()/isChecked()-style checks when the eval returns an unexpected type — typically the execution context was destroyed mid-wait or the injected script mismatches the binary.

Common situations: Page navigating while an action waits for actionability; custom xk6 builds with stale injected script; rare races right at timeout expiry.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/63985052a143c6a1. Report an issue: GitHub.