grafana/k6 · error
waiting for selector %q: %w
Error message
waiting for selector %q: %w
What it means
Wrapped failure from ElementHandle.WaitForSelector (elementHandle.waitForSelector(selector)). The inner path parses the selector (NewSelector — invalid syntax fails immediately), steps into frames when the selector contains iframe boundaries (>>), then waits for the target state. It fails on invalid selector syntax, on timeout waiting for the requested state, on strict-mode violations, or when the frame chain cannot be resolved.
Source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1582
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(
ctx context.Context,
opts evalOptions, js string, args ...any,
) (any, error) {
script, err := h.execCtx.getInjectedScript(h.ctx)
if err != nil {
return nil, fmt.Errorf("getting injected script: %w", err)
}
return h.eval(ctx, opts, js, append([]any{script}, args...)...)
}
View on GitHub (pinned to 93accf6570)
Solutions
- Verify the selector matches in browser devtools against the exact page state, and prefer stable data-* attributes
- Increase the timeout and pick the right state: el.waitForSelector(sel, { state: 'visible', timeout: '30s' })
- For multiple matches, scope the selector more tightly or pass strict: false deliberately
- For chained iframe selectors, confirm each frame segment matches an existing <iframe> element
Example fix
// before
const ok = page.$('#form').waitForSelector('div.row', { timeout: '1s' });
// after
const ok = page.$('#form').waitForSelector('div.row[data-qa=row]', { state: 'visible', timeout: '30s' }); Defensive patterns
Strategy: validation
Validate before calling
// fail fast on syntax and emptiness before waiting
const parsed = page.$(selector);
if (parsed === null && strictModeWanted) {
// let waitForSelector drive the wait, but assert the selector is well-formed
}
page.waitForLoadState('domcontentloaded'); Try / catch
try {
return el.waitForSelector(sel, { state: 'visible', timeout: '30s' });
} catch (e) {
const msg = String(e);
if (msg.includes('strict mode violation')) {
return el.waitForSelector(sel, { strict: false, timeout: '30s' });
}
if (msg.includes('waiting for selector')) {
throw new Error(`selector ${sel} never matched: ${e}`);
}
throw e;
} Prevention
- Verify selectors in devtools against the real page state
- Prefer stable data-testid/data-qa attributes over generated classes
- Set explicit state and timeout options instead of defaults
When it happens
Trigger: Malformed CSS/XPath/text selector that NewSelector rejects; selector never matching before opts.Timeout; state: 'visible' while the element exists but stays hidden; strict: true with multiple matches ('strict mode violation, multiple elements returned for selector query'); iframe part (>> iframe ...) of a chained selector not found, giving 'finding iframe with selector' failures.
Common situations: Selectors authored against one environment but the app renders differently in another; waiting inside an element handle scope where the sub-tree never gets the node; dynamic class names/IDs from CSS-in-JS; strict-by-default queries hitting duplicated DOM.
Related errors
- finding iframe with selector %q: %w
- getting iframe frame: %w
- unchecking %q: %w
- checking element is checked %q: %w
- double clicking on %q: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/a384878e96b10960.
Report an issue: GitHub.