grafana/k6 · error
selecting option on %q: %w
Error message
selecting option on %q: %w
What it means
Frame.SelectOption() wraps the internal select-option action; any failure — element not found, not a <select> element, actionability timeout, or a mid-action detach — is reported as 'selecting option on "<selector>": <cause>'. The actionable detail is the wrapped cause, not the prefix.
Source
Thrown at internal/js/modules/k6/browser/common/frame.go:1706
act := f.newAction(
selector, DOMElementStateAttached, opts.Strict, press,
[]string{}, false, withRetry, opts.NoWaitAfter, opts.Timeout,
)
if _, err := call(f.ctx, act, opts.Timeout); err != nil {
return errorFromDOMError(err)
}
return nil
}
// SelectOption selects the given options and returns the array of
// option values of the first element found that matches the selector.
func (f *Frame) SelectOption(selector string, values []any, popts *FrameSelectOptionOptions) ([]string, error) {
f.log.Debugf("Frame:SelectOption", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector)
v, err := f.selectOption(selector, values, popts)
if err != nil {
return nil, fmt.Errorf("selecting option on %q: %w", selector, err)
}
applySlowMo(f.ctx)
return v, nil
}
func (f *Frame) selectOption(selector string, values []any, opts *FrameSelectOptionOptions) ([]string, error) {
selectOption := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return handle.selectOption(apiCtx, values)
}
act := f.newAction(
selector, DOMElementStateAttached, opts.Strict, selectOption,
[]string{}, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
)
v, err := call(f.ctx, act, opts.Timeout)
if err != nil {
return nil, errorFromDOMError(err)View on GitHub (pinned to 93accf6570)
Solutions
- Confirm the target is a real <select> element (inspect with evaluate(() => document.querySelector(sel).tagName)); if it is a custom widget, click it and click options instead.
- Pass the right matcher shape: { value: 'x' }, { label: 'Text' }, or { index: 2 }.
- Wait for the select to be visible/enabled before the call.
- If the select is styled but native, use { force: true } to bypass visibility checks.
Example fix
// before
await frame.selectOption('.nice-select', 'opt1'); // div wrapper, not <select>
// after
await frame.selectOption('select#country', { value: 'opt1' });
// or for custom dropdowns:
await frame.click('.dropdown-toggle');
await frame.click('li[data-value="opt1"]'); Defensive patterns
Strategy: validation
Validate before calling
const tag = await frame.evaluate(s => document.querySelector(s)?.tagName, sel);
if (tag !== 'SELECT') throw new Error(`${sel} is ${tag}, not <select>`); Type guard
const isNativeSelect = (t) => t === 'SELECT';
Try / catch
try { await frame.selectOption(sel, { value: v }); }
catch (e) { if (/selecting option on/.test(e.message)) { /* check tagName, matcher shape, visibility */ } throw e; } Prevention
- Confirm the target is a real <select> element before calling
- Pass { value } / { label } / { index } matchers, not raw guesses
- For custom dropdown widgets, click through options instead
When it happens
Trigger: frame.selectOption(sel, values) where sel does not match a <select> element (e.g. a custom div dropdown), the select is hidden/disabled, values do not match any option, or strict mode finds multiple matches. Also when the element detaches between resolution and click.
Common situations: Modern UIs use div/role=listbox dropdowns where selectOption cannot work — a real <select> is required; selecting by value when the option only has a label; hidden native selects styled with display:none (materialize/bootstrap overrides).
Related errors
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/4d23b76319673754.
Report an issue: GitHub.