grafana/k6 · error
waiting for element state %q: %w
Error message
waiting for element state %q: %w
What it means
Wrapped failure from the public ElementHandle.WaitForElementState (elementHandle.waitForElementState(state)). The inner waitForElementState runs the injected waitForElementStates script with [state]; it fails when the element never reaches the state within opts.Timeout (mapped to ErrTimedOut via 'timed out' detection), when the state string is not one the injected script knows, or when the element is detached/not an element.
Source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1572
return nil, handle.typ(apiCtx, text, KeyboardOptions{})
}
typeAction := h.newAction(
[]string{}, typ, false, withRetry, opts.NoWaitAfter, opts.Timeout,
)
if _, err := call(h.ctx, typeAction, opts.Timeout); err != nil {
return fmt.Errorf("typing text %q: %w", text, err)
}
applySlowMo(h.ctx)
return nil
}
// WaitForElementState waits for the element to reach the given state.
func (h *ElementHandle) WaitForElementState(state string, opts *ElementHandleWaitForElementStateOptions) error {
_, err := h.waitForElementState(h.ctx, []string{state}, opts.Timeout)
if err != nil {
return fmt.Errorf("waiting for element state %q: %w", state, err)
}
return nil
}
// WaitForSelector waits for the selector to appear in the DOM.
func (h *ElementHandle) WaitForSelector(selector string, opts *FrameWaitForSelectorOptions) (*ElementHandle, error) {
handle, err := h.waitForSelector(h.ctx, selector, opts)
if err != nil {
return nil, fmt.Errorf("waiting for selector %q: %w", selector, err)
}
return handle, nil
}
// evalWithScript evaluates the given js code in the scope of this ElementHandle and returns the result.
// The js code can call helper functions from injected_script.js.
func (h *ElementHandle) evalWithScript(View on GitHub (pinned to 93accf6570)
Solutions
- Increase opts.Timeout: el.waitForElementState('visible', { timeout: '60s' })
- Use a supported state: visible, hidden, stable, enabled, editable (attached/detached belong to waitForSelector)
- If the underlying app is stuck (backend error), fix or stub that dependency instead of lengthening waits
- For 'hidden' waits on elements that may already be gone, tolerate detachment by catching and checking the element still exists
Example fix
// before
el.waitForElementState('attached', { timeout: '5s' }); // invalid state for this API
// after
el.waitForElementState('visible', { timeout: '30s' }); Defensive patterns
Strategy: validation
Validate before calling
const VALID_STATES = ['visible', 'hidden', 'stable', 'enabled', 'editable'];
function assertValidState(state) {
if (!VALID_STATES.includes(state)) {
throw new Error(`invalid element state ${state}; expected one of ${VALID_STATES.join(', ')}`);
}
}
assertValidState(state);
el.waitForElementState(state, { timeout: '30s' }); Type guard
const isElementState = (s) => ['visible', 'hidden', 'stable', 'enabled', 'editable'].includes(s);
Try / catch
try {
el.waitForElementState(state, { timeout: '30s' });
} catch (e) {
if (String(e).includes('timed out')) {
// app never reached the state: fail with context, not a retry loop
throw new Error(`element never became ${state}: ${e}`);
}
throw e;
} Prevention
- Validate the state string against the supported set before calling
- Size timeouts to the app's real transition duration
- Do not use waitForSelector-only states (attached/detached) here
When it happens
Trigger: Waiting for 'visible' on an element that stays hidden until timeout; waiting for 'stable' on an infinitely animating element; passing an unsupported state string; waiting on a handle whose node was removed from the DOM.
Common situations: Spinners and skeletons that never resolve on failed backend calls; elements toggled by CSS transitions; waiting for 'enabled' on buttons gated by async form validation; states confused with waitForSelector states like 'attached'.
Related errors
- filling element: %w
- selecting text: %w
- checking state %q of element %q
- finding clickable point: %w
- waiting for states %v of element %q
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/d2c688106843db4b.
Report an issue: GitHub.