grafana/k6 · error

options: expected array, got %T

Error message

options: expected array, got %T

What it means

Defensive branch inside ConvertSelectOptionValues: the values argument exported as a Go slice kind, but sobek could not export it into []any. With plain JavaScript arrays this practically never happens; it guards exotic runtime values (custom array-like objects produced by native bindings or corrupted sobek values). When it does fire, selectOption rejects with 'parsing select option values: options: expected array, got <type>'.

Source

Thrown at internal/js/modules/k6/browser/browser/mapping.go:63

		return nil, fmt.Errorf("parsing click options: %w", err)
	}
	return copts, nil
}

func ConvertSelectOptionValues(rt *sobek.Runtime, values sobek.Value) ([]any, error) {
	if k6common.IsNullish(values) {
		return nil, nil
	}

	var (
		opts []any
		t    = values.Export()
	)
	switch values.ExportType().Kind() {
	case reflect.Slice:
		var sl []any
		if err := rt.ExportTo(values, &sl); err != nil {
			return nil, fmt.Errorf("options: expected array, got %T", values)
		}

		for _, item := range sl {
			switch item := item.(type) {
			case string:
				// Strings will match values or labels
				valOpt := common.SelectOption{Value: new(string)}
				*valOpt.Value = item
				labelOpt := common.SelectOption{Label: new(string)}
				*labelOpt.Label = item
				opts = append(opts, &valOpt, &labelOpt)
			case map[string]any:
				opt, err := extractSelectOptionFromMap(item)
				if err != nil {
					return nil, err
				}

				opts = append(opts, opt)

View on GitHub (pinned to 93accf6570)

Solutions

  1. Pass a plain JavaScript array literal: selectOption(['red', { label: 'Green' }])
  2. Convert exotic values with Array.from(values) before calling selectOption
  3. Rebuild the value from raw data (strings and plain objects) rather than passing foreign objects
  4. Report persistent cases to k6 browser module maintainers with a minimal reproducer

Example fix

// before
await page.locator('select').selectOption(exoticArrayLike);

// after
await page.locator('select').selectOption(Array.from(exoticArrayLike));
Defensive patterns

Strategy: type-guard

Validate before calling

function toPlainArray(values) {
  if (values === null || values === undefined) return values;
  if (Array.isArray(values)) return values; // plain JS array always exports cleanly
  if (typeof values === 'string' || typeof values === 'object') return Array.from(values);
  throw new TypeError(`selectOption values must be a string, array, or object, got ${typeof values}`);
}

Type guard

function isPlainSelectArray(v) {
  return Array.isArray(v);
}

Try / catch

try {
  await locator.selectOption(values, opts);
} catch (e) {
  if (/expected array/.test(String(e.message))) {
    // rebuild as a literal array and retry once with validated items
    const plain = (Array.isArray(values) ? values : Array.from(values ?? []))
      .map((x) => (typeof x === 'number' ? { index: x } : x));
    await locator.selectOption(plain, opts);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Passing a selectOption values argument that is a slice-typed sobek value not produced from a plain JS array — e.g. a value marshaled from Go code or a native object whose array conversion fails during ExportTo.

Common situations: Extensions or xk6 modules feeding non-standard array objects into the browser module; edge cases after runtime upgrades that change sobek export behavior.

Related errors


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