grafana/k6 · error

unexpected select element type %T

Error message

unexpected select element type %T

What it means

After the selectOption action runs, k6 asserts the CDP result is a jsHandle. If the browser returned a primitive value instead of a JSHandle (a protocol/eval-shape mismatch), the type assertion fails and you get 'unexpected select element type <Go type>'. This indicates the internal injected script returned an unexpected shape, typically after a version skew or context switch mid-eval.

Source

Thrown at internal/js/modules/k6/browser/common/frame.go:1728

	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)
	}
	selectHandle, ok := v.(jsHandle)
	if !ok {
		return nil, fmt.Errorf("unexpected select element type %T", v)
	}

	// pack the selected <option> values inside <select> into a slice
	optHandles, err := selectHandle.getProperties()
	if err != nil {
		return nil, fmt.Errorf("getProperties: %w", err)
	}
	vals := make([]string, 0, len(optHandles))
	for _, oh := range optHandles {
		val, err := oh.JSONValue()
		if err != nil {
			return nil, fmt.Errorf("reading value: %w", err)
		}
		vals = append(vals, val)
		if err := oh.dispose(); err != nil {
			return nil, fmt.Errorf("optionHandle.dispose: %w", err)
		}
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Re-run the action after the page settles: wait for load state, then call selectOption again.
  2. Upgrade (or pin) k6 so the Go browser module and the chromium binary ship from the same release; clear the browser cache directory if binaries were downloaded separately.
  3. If it reproduces deterministically on one page, capture a trace/DEBUG log and report it — this is an internal contract violation, not a script bug.

Example fix

// before
await page.selectOption('#sel', 'a'); // page navigates during call

// after
await page.waitForLoadState('load');
const v = await page.selectOption('#sel', 'a'); // stable context
Defensive patterns

Strategy: retry

Validate before calling

await page.waitForLoadState('load'); // ensure stable execution context before selectOption

Try / catch

try { return await page.selectOption(sel, v); }
catch (e) { if (/unexpected select element type/.test(e.message)) { await page.waitForLoadState('load'); return page.selectOption(sel, v); } throw e; }

Prevention

When it happens

Trigger: selectOption returns a value (nil, string, map) instead of a JSHandle because the evaluation ran in a fresh/replaced execution context (navigation during the call), or the injected script's return contract changed between k6 and the bundled browser binaries.

Common situations: Page navigates while selectOption is executing; chromium binary version mismatch after upgrading k6 without a clean build; renderer crash mid-action. Rare — most users will never see it unless the page changes under the action.

Related errors


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