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
- Retry the action after the page settles and the element is re-located
- Upgrade to a clean matching k6 build
- Increase the timeout so waits don't race navigation
- 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
- Expect this from any Is*() helper and action prechecks
- Avoid actions that race navigation
- Keep k6 versions matched
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
- waiting for element state %q: %w
- getting injected script: %w
- waitFor retry threshold reached
- checking state %q of element %q
- finding clickable point: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/63985052a143c6a1.
Report an issue: GitHub.